Laravel 5

EagerLoading selon conditions

  • Avatar de LaraSharp
    Membre depuis :
    03/01/2018
    Messages :
    16

    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') ;
    }
  • Avatar de bestmomo
    Membre depuis :
    07/04/2013
    Messages :
    2472

    Bonjour,

    En fait tu veux faire du polymorphisme...

  • Avatar de LaraSharp
    Membre depuis :
    03/01/2018
    Messages :
    16

    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.

  • Avatar de bestmomo
    Membre depuis :
    07/04/2013
    Messages :
    2472

    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...

  • Avatar de LaraSharp
    Membre depuis :
    03/01/2018
    Messages :
    16

    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 ?
  • Avatar de LaraSharp
    Membre depuis :
    03/01/2018
    Messages :
    16

    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();

  • Avatar de bestmomo
    Membre depuis :
    07/04/2013
    Messages :
    2472

    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.

  • Avatar de LaraSharp
    Membre depuis :
    03/01/2018
    Messages :
    16

    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;
    });
  • Avatar de bestmomo
    Membre depuis :
    07/04/2013
    Messages :
    2472

    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.

Vous ne pouvez pas répondre à ce sujet.