Laravel基础数据库with函数技术咨询及致谢
Hey there! Let's break down Laravel's with() function—total game-changer for handling database relationships without those annoying N+1 query issues. I'll walk you through the basics, use cases, and some pro tips to level up your Eloquent skills.
with() Function: A Complete Guide to Eager Loading What is with() actually for?
At its core, with() enables eager loading—a way to load all necessary related model data in advance, instead of triggering new database queries every time you access a relationship.
Let's use a classic example to illustrate the problem it solves:
Suppose you have a Post model that hasMany Comment models. Without eager loading:
$posts = Post::all(); foreach ($posts as $post) { // Each loop triggers a new SELECT query for comments on this post echo "Post has " . $post->comments->count() . " comments"; }
This results in 1 + N queries (1 for all posts, N for each post's comments). With with(), we fix this:
$posts = Post::with('comments')->get(); foreach ($posts as $post) { // No extra queries—comments are already loaded! echo "Post has " . $post->comments->count() . " comments"; }
Now we only run 2 queries total: one for posts, one for all comments linked to those posts.
Loading Multiple Relationships at Once
You can load multiple unrelated relationships in a single with() call by passing an array of relationship names:
// Load posts with their author (belongsTo User) and category (belongsTo Category) $posts = Post::with('author', 'category')->get();
Loading Nested Relationships
If your relationships have their own relationships (e.g., a Comment belongs to a User), use dot notation to load nested data:
// Load posts, their comments, and each comment's author $posts = Post::with('comments.author')->get();
Constraining Eager Loads
You don't always need every related record. Use a closure to filter or modify the eager load query:
// Only load published comments for each post $posts = Post::with(['comments' => function ($query) { $query->where('is_published', true)->orderBy('created_at', 'desc'); }])->get();
You can also load only specific fields from related models (just remember to include the foreign key so Laravel can match records):
// Load only the author's id, name, and email (include user_id, the foreign key) $posts = Post::with(['author:id,name,email,user_id'])->get();
Lazy Eager Loading
If you already fetched a model collection and later decide you need related data, use load() instead of with():
$posts = Post::all(); // Later in your code, load comments for the existing posts $posts->load('comments');
Use loadMissing() to only load relationships that haven't been loaded yet:
// Load comments only if they aren't already present $posts->loadMissing('comments');
Bonus: withCount() for Relationship Counts
If you just need the number of related records (not the records themselves), use withCount() to avoid loading unnecessary data:
// Add a `comments_count` attribute to each post $posts = Post::withCount('comments')->get(); foreach ($posts as $post) { echo $post->comments_count; }
You can even add constraints to the count:
// Count only published comments, and name the attribute `published_comments_count` $posts = Post::withCount([ 'published_comments' => function ($query) { $query->where('is_published', true); } ])->get();
内容的提问来源于stack exchange,提问作者NewbieCoder

