2017-06-22 1 views
2

J'ai diverses relations au sein de mon EloquentModels qui ressemblent à ceci:Laravel Eloquent - Ne pas exécuter la requête de la relation si la valeur de la colonne est NULL ou 0

public function main_image() 
{ 
    return $this->hasOne(Media::class, 'id', 'main_image_id'); 
} 

Cependant, il exécutera une requête SQL si le main_image_id est null ou 0, donc je finis avec un certain nombre de questions comme ceci:

select * from `media` where `media`.`id` is null and `media`.`id` is not null limit 1 

qui, évidemment, ne retournera rien, mais gaspille encore des ressources. Y a-t-il un moyen de vérifier automatiquement cela?

Actuellement ce que je fais est d'avoir une méthode, comme hasMainImage(), qui vérifie que main_image_id n'est pas nul et pas 0, mais une grande partie du système actuel utilise déjà les relations, et je me demandais si je pouvais ajouter la vérification à la méthode relationnelle elle-même?

J'ai essayé d'ajouter un chèque et retourner null si la colonne n'a pas de valeur réelle, mais j'ai un Exception qu'il doit retourner un objet Relation. Ou si je suis en train de charger Eager, je reçois l'erreur suivante:

Call to a member function addEagerConstraints() on null

public function main_image() 
{ 
    if (!$this->main_image_id) { 
     return null; 
    } 

    return $this->hasOne('App\Modules\Media\Models\Media', 'id', 'main_image_id'); 
} 

Merci pour votre aide!

EDIT: A peut-être plus clair exemple:

$page = Page::find(1); 
var_dump($page->main_image); // This will run a query as shown above that is guaranteed to return nothing 
// Since at this point system knows that $page->main_image_id is 0 or null, I would like to use that to not run the query and automatically set $page->main_image to null 
+0

Faire un 'with' utilise des ressources supplémentaires. Vous ne devriez pas le faire en premier lieu, ne pas le faire partout et ensuite essayer de le contourner. – apokryfos

+0

'with' n'est pas utilisé partout, uniquement lorsque plusieurs modèles sont chargés en même temps. Lorsqu'une seule instance est chargée, 'with 'n'est pas utilisé et des appels comme' $ page-> main_image' sont effectués. Ce sont les appels que j'essaie d'optimiser ici – Giedrius

+0

Il n'y a aucun avantage supplémentaire si vous faites cela. La jointure se produira de toute façon, cela retournera juste moins de choses. Je suppose bien sûr que vous avez une relation un-à-un ici. – apokryfos

Répondre

0

Vous déclarez vos relations en mauvais ordre, Eloquent documentation est clair à ce sujet.

L'entité qui n'a pas de sens par elle-même (sans son «parent», vous pouvez dire) devrait incorporer la relation «belongsTo» (comme la documentation dit inverse). Pour la démonstration, disons que vous avez un modèle utilisateur et que vous avez beaucoup de détails sur cet utilisateur pour créer un modèle de détail.

Maintenant modèle utilisateur doit avoir le détail relation:

public function detail() { 
    return $this->hasOne('App\Detail', 'user_id', 'id'); //you can see the difference here from your code sample, you have 2nd and 3rd parameter reversed 
} 

Et le modèle de détail devrait avoir une relation utilisateur:

public function user() 
{ 
    return $this->belongsTo('App\User'); 
} 
+0

Ce n'est pas la structure que j'ai actuellement. J'ai le modèle 'Page', et le modèle' Media'. Le modèle 'Media' est un modèle autonome qui n'est attaché à aucun autre (car il peut être utilisé plusieurs fois par différents modèles et instances de modèle). 'Page' a une méthode' main_image' (telle que définie dans quetstion) qui définit la relation avec 'Media'. Je ne veux pas lancer une requête SQL si je sais d'avance qu'elle ne retournera rien. Je ne suis pas sûr comment la définition de 'belongsTo' dans le modèle' Media' résout ce problème? Je n'ai pas besoin d'accéder à d'autres modèles depuis l'instance 'Media' de toute façon. – Giedrius

+0

Donc vous utilisez des relations polymorphes non? – Kyslik

+0

Pas dans ce cas. 'Page' Model peut avoir un seul' Media' lié à celui-ci en tant que 'main_image', cependant, le même modèle' Media' peut être lié à d'autres pages comme 'main_image', et un certain nombre d'autres modèles comme différents types d'images . Donc 'Page'" a un "objet Media, qui est référencé dans la table' pages' comme "main_image_id'. Je me demande si je devrais utiliser la relation 'belongsTo' ici? Et si cela ferait une différence dans l'exécution des requêtes? Je suppose qu'il va exécuter les requêtes SQL, je veux me débarrasser de l'une ou l'autre façon, car il pourrait y avoir un 0 là-dedans. – Giedrius