Laravel 5

EagerLoading selon conditions

Avatar de LaraSharp
LaraSharp

Bonjour,

Je souhaiterais embarquer les relations dans mes modeles selon un champ précis. Le soucis est que l'application a 2 tables de type sociétés qu'on ne peut pas transformer en une seule table (sinon ça aurait été trop simple).

ex : Demande::with('societes')->get(); Et récuperer dans ma demande, la société enregistré dans la table sociétéTypeA si le paiement est de Type A Et récuperer dans ma demande, la société enregistré dans table sociétéTypeB si le paiement est de Type B

J'avais pensé dans la fonction sociétés faire un truc style if ( $this->paiements()->type =A)... mais requetant sur toutes les demandes, ça ne passe pas avec $this. (voir function societes(), je ne sais pas quoi mettre à la place de mes lignes commentés s'il faut faire ainsi)

Fonction dans mon modele Demande :

public function societes ()
{
    // pour les demandes dont le paiemenst()->type = A  
      return $this->hasOne('App\Models\societeTypeA', 'demande_id', 'id');
    
    // pour les demandes dont le paiement()->type = B

return $this->hasOne('App\Models\societeTypeB, 'demande_id', 'id'); }

public function paiements(){ 
    return $this->hasOne('App\Models\Paiement', 'id', 'paiement_id') ;
}
Posté il y a 1 an
Avatar de bestmomo
bestmomo

Bonjour,

En fait tu veux faire du polymorphisme...

Posté il y a 1 an
Avatar de LaraSharp
LaraSharp

Non car les 2 tables sociétés sont carrément différentes, une provient d'une appli oracle (appli tiers non modifiable), l'autre d'une base MySQL , ils n'ont absolument aucun champs en commun en plus.

Posté il y a 1 an
Avatar de bestmomo
bestmomo

Dans ce cas je ferais deux fonctions pour les relations et je mettrais une condition dans la requête, du genre :

$demandes = Demande::query()->when('demande.type', 'A', function ($query)  {
                return $query->with(societesA);
            })->when('demande.type', 'B', function ($query) {
                return $query->with(societesG);
            })->get();

Il faut voir si c'est bien digéré par Eloquent...

Posté il y a 1 an
Avatar de LaraSharp
LaraSharp

Bonjour Bestmomo,

Merci pour ton approche qui je pense correspond à ce qu'il faudrait mais la syntaxe n'est pas tout à fait bonne. Si dans le when on met une virgule, il attend une fonction en callback, et non une valeur. Dans quelques forums, j'ai vu que certains mettaient == , mais je n'ai pas trouvé la bonne syntaxe non plus,

ex : testé : ne retourne en aucun cas la relation societe , donc KO

   $demande = Demande::with(array('paiement' => function($query)
    {
        $query->when('demande.paiement.type' == 'A', function($query) {
         return $query->with('societeA');
        });
        $query->when('demande.paiement.type' == 'B', function($query) {
           return $query->with('societeB');
        });
    }))->get();
    

ex : renvoie la relation société même si le type n'est ni A ni B : donc KO .

     $demande = Demande::with(array('paiement' => function($query)
    {
        $query->when('demande.paiement.type == A', function($query) {
         return $query->with('societeA');
        });
        $query->when('demande.paiement.type == B', function($query) {
           return $query->with('societeB');
        });
    }))->get();
    
    Vois-tu quelle est la bonne syntaxe à mettre ?
Posté il y a 1 an
Avatar de LaraSharp
LaraSharp

Dans la doc officielle, il y a cette aide qui semble correspondre, mais je n'ai pas réussi à la faire fonctionner avec ma relation, ça me récupère à chaque fois que le premier cas. Dans l'autre cas, la relation est à chaque fois à null .

The when method only executes the given Closure when the first parameter is true. If the first parameter is false, the Closure will not be executed.

You may pass another Closure as the third parameter to the when method. This Closure will execute if the first parameter evaluates as false. To illustrate how this feature may be used, we will use it to configure the default sorting of a query:

$sortBy = null;

$users = DB::table('users') ->when($sortBy, function ($query) use ($sortBy) { return $query->orderBy($sortBy); }, function ($query) { return $query->orderBy('name'); }) ->get();

Posté il y a 1 an
Avatar de bestmomo
bestmomo

Finalement je pense pas que ce soit la bonne direction avec when...

A la limite tu fais deux requêtes et tu fusionnes les résultats.

Ou alors une sous-requête avec selectSub qu'on utilise peu, j'ai lu récemment un article intéressant sur ce sujet.

Posté il y a 1 an
Avatar de LaraSharp
LaraSharp

Est-ce qu'une solution dans ce style pourrait fonctionner ? Le map est plus connu mais ça ne veut pas ajouter ma relation 'societeA' ou 'sociétéB , ma syntaxe ne doit pas être correcte :

    $demande = Demande::with('paiement')->get()->map(function ($query)
    {
        if ($query->paiement->type == 'A')
        {
            $query->with('societeA');
        }
        if ($query->paiement->type == 'B')
        {
            $query->with('societeB');
        }
        return $query;
    });
Posté il y a 1 an
Avatar de bestmomo
bestmomo

Non ça ira pas comme ça, tu dois vraiment avoir deux requêtes avec chacune le chargement de la bonne relation, soit distinctes et tu fusionnes ensuite les collections, soit avec une sous-requête.

Posté il y a 1 an

Vous ne pouvez pas répondre à ce sujet.