J'ai trouvé le concept et la signification derrière ces méthodes un peu déroutants, est-il possible pour quelqu'un de m'expliquer quelle est la différence entre has
et with
est, dans le contexte d'un exemple (si possible)?
J'ai trouvé le concept et la signification derrière ces méthodes un peu déroutants, est-il possible pour quelqu'un de m'expliquer quelle est la différence entre has
et with
est, dans le contexte d'un exemple (si possible)?
Réponses:
with()
est pour un chargement rapide . Cela signifie essentiellement que, le long du modèle principal, Laravel préchargera la ou les relations que vous spécifiez. Cela est particulièrement utile si vous avez une collection de modèles et que vous souhaitez charger une relation pour chacun d'eux. Parce qu'avec un chargement rapide, vous n'exécutez qu'une seule requête DB supplémentaire au lieu d'une pour chaque modèle de la collection.
Exemple:
User > hasMany > Post
$users = User::with('posts')->get();
foreach($users as $user){
$users->posts; // posts is already loaded and no additional DB query is run
}
has()
consiste à filtrer le modèle de sélection en fonction d'une relation. Il agit donc de manière très similaire à une condition WHERE normale. Si vous utilisez uniquement has('relation')
cela signifie que vous souhaitez uniquement obtenir les modèles qui ont au moins un modèle lié dans cette relation.
Exemple:
User > hasMany > Post
$users = User::has('posts')->get();
// only users that have at least one post are contained in the collection
whereHas()
fonctionne de la même manière que has()
mais vous permet de spécifier des filtres supplémentaires pour le modèle associé à vérifier.
Exemple:
User > hasMany > Post
$users = User::whereHas('posts', function($q){
$q->where('created_at', '>=', '2015-01-01 00:00:00');
})->get();
// only users that have posts from 2015 on forward are returned
whereHas
sur la relation utilisateur lors de la requête post.
whereHas
utilise use Illuminate\Database\Eloquent\Builder;
ce qui est alors avec function(Builder $query)
. La plupart des exemples que j'ai vus, utilisent le Builder
, passez simplement la requête $, quelle est la bonne façon?
Le document a déjà expliqué l'utilisation. J'utilise donc SQL pour expliquer ces méthodes
En supposant qu'il y en Order (orders)
a plusieurs OrderItem (order_items)
.
Et vous avez déjà construit la relation entre eux.
// App\Models\Order:
public function orderItems() {
return $this->hasMany('App\Models\OrderItem', 'order_id', 'id');
}
Ces trois méthodes sont toutes basées sur une relation .
Résultat: with()
retourne l'objet modèle et ses résultats associés.
Avantage: c'est un chargement rapide qui peut éviter le problème N + 1 .
Lorsque vous utilisez Eloquent Builder suivant:
Order::with('orderItems')->get();
Laravel change ce code en seulement deux SQL :
// get all orders:
SELECT * FROM orders;
// get the order_items based on the orders' id above
SELECT * FROM order_items WHERE order_items.order_id IN (1,2,3,4...);
Et puis laravel fusionne les résultats du deuxième SQL comme différents des résultats du premier SQL par clé étrangère . Enfin, retournez les résultats de la collecte.
Donc, si vous avez sélectionné des colonnes sans la clé étrangère en fermeture, le résultat de la relation sera vide:
Order::with(['orderItems' => function($query) {
// $query->sum('quantity');
$query->select('quantity'); // without `order_id`
}
])->get();
#=> result:
[{ id: 1,
code: '00001',
orderItems: [], // <== is empty
},{
id: 2,
code: '00002',
orderItems: [], // <== is empty
}...
}]
Has
retournera l'objet du modèle que sa relation n'est pas vide .
Order::has('orderItems')->get();
Laravel change ce code en un SQL :
select * from `orders` where exists (
select * from `order_items` where `order`.`id` = `order_item`.`order_id`
)
whereHas
et les orWhereHas
méthodes pour mettre des where
conditions à vos has
requêtes. Ces méthodes vous permettent d'ajouter des contraintes personnalisées à une contrainte de relation .
Order::whereHas('orderItems', function($query) {
$query->where('status', 1);
})->get();
Laravel change ce code en un SQL :
select * from `orders` where exists (
select *
from `order_items`
where `orders`.`id` = `order_items`.`order_id` and `status` = 1
)
with('relation')
inclura les données de la table connexe dans la collection retournée,has('relation')
etwhereHas('relation')
ne pas inclure les données de la table correspondante. Vous devrez donc peut-être appeler à la foiswith('relation')
ainsi quehas()
ouwhereHas()
.