简体   繁体   中英

Laravel - How to eager load many to many relationships

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

}

Edit

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;

Edit

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM