How would I eager load articles that belong to a category with article user, comments and comments user ?
Laravel version is 4.2.17
Using the query event listener, and dumping sql queries to the page. The HomeContoller method works fine, eager loads all of the articles without the N+1 problem.
However the getCategory method loads all the articles ok but does an sql query inside the foreach loop to get the article user, comments and comments user.
-- Database tables
articles
- id
- user_id
- body
comments
- id
- user_id
- article_id
- body
users
- id
- name
cat
- id
- name
article_cat
- id
- article_id
- cat_id
-- Models
class Article extends Eloquent {
public function user() {
return $this->belongsTo('User');
}
public function comments() {
return $this->hasMany('Comment');
}
}
class Comment extends Eloquent {
public function article() {
return $this->belongsTo('Article');
}
public function user() {
return $this->belongsTo('User');
}
}
class User extends Eloquent implements UserInterface, RemindableInterface {
public function articles() {
return $this->hasMany('article');
}
public function comments() {
return $this->hasMany('comment');
}
}
class Cat extends Eloquent {
public function articles() {
return $this->belongsToMany('Article');
}
}
-- Controllers
class HomeController extends BaseController {
// Get all articles
public function home() {
$articles = Article::with(['user', 'cats', 'comments', 'comments.user'])->get();
}
}
class CategoryController extends BaseController {
public function getCategory($categoryid) {
// How do I eager load articles the belong to this category with the article user, comments and comments user
$category = Cat::with('articles')
->find($categoryid)
->articles()
->get();
}
}
Have made some changes to the controller but it's still not eager loading, below is the new controller ...
public function getCategory($categoryid) {
$cat = Cat::where('id', $categoryid)->firstOrFail();
$category = Cat::with('articles')
->with('articles.user')
->with('articles.comments')
->find($categoryid)
->articles()
->orderBY('created_at', 'desc')
->take(Config::get('settings.num_posts'))
->get();
foreach ($category as $article) {
echo '<p> Article body = ' . $article->body . '</p>';
echo '<p> Article user = ' . $article->user->name . '</p>';
echo '<p> Article user photo = ' . $article->user->photo . '</p>';
echo '<p> Comments = ' . $article->comments . '</p>';
echo '<hr>';
}
exit();
Just use a dot to load in the related models.
$category = Cat::with('articles')
->with('articles.user')
->with('articles.comments')
->find($categoryid)
->get();
And then access your articles.
$category->articles;
You can always try eager loading within the relationship if you're always going to need the user on each comment or user, which I assume you will.
For comments.
public function comments() {
return $this->hasMany('Comment')->with('user');
}
And for articles.
public function articles() {
return $this->belongsToMany('Article')->with('user');
}
I've had similar issues and I resolved it by adding a foreign key to my models. So in your Comment
model, it's best to add your foreign_key id like this:
class Comment extends Eloquent {
public function article() {
return $this->belongsTo('Article', 'article_id');
}
public function user() {
return $this->belongsTo('User', 'user_id');
}
}
Same with your user model.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.