0

I would like to have a model that belongs to another one. In my controller, I'd like to get all items in that model, but I want the attributes from the table it belongs to as well. For example:

class Comment extends Eloquent {

    public function post()
    {
        return $this->belongsTo('Post');
    }

}

In my controller I can do the following to get the comment data:

$comments = Comment::first();

However, that will only give me data from the comments table (and no joined data from the posts table). I would like the data from the posts table for the row that each comment belongs to available as attributes to my Comment model. I know that I can also do the following to get the data from the posts table:

$comments = Comment::first();

The issue with doing it this way is that it uses two database queries (#1 to get the comment, and #2 to get the post data that it belongs to). Is there a way that I get the data from both tables into my model, equivalent to a join statement:

SELECT * FROM comments LEFT JOIN posts ON comments.post_id = posts.id

I Know that I build a join query manually without using my Comment or Post models, but I have several methods in my Comment model that I'd like to be able to use with the data that is retrieved. Anyone know how I can accomplish this?

1
  • You must first Retrieve the Post and then Retrieve your Comment based on your Post Like this $comments = $post->comments()->orderBy('created_at', 'DESC')->get(); Commented Sep 11, 2013 at 4:45

3 Answers 3

4

From the documentation on eager loading:

Thankfully, we can use eager loading to drastically reduce the number of queries. The relationships that should be eager loaded may be specified via the with method [...]

Using the with() parameter will use a constant number† of queries in a one-to-many relationship. Therefore, this is query should retrieve your comments with their related post in one query:

$comments = Comments::with('post')->get();

† A Constant number of queries as opposed to linearly increasing in query count per number of comments

Sign up to request clarification or add additional context in comments.

2 Comments

If I add an event listener for the queries, it does show that there are two separate queries still running to get the data: select * from comments select * from posts where posts.id in (?, ?) However, if I am retrieving MANY comments, it is still only using 2 total queries instead of 2 queries for EVERY comment. I think that should be good enough for me.
Good to know! It appears it's not "one" but rather "few" (constant) queries. Thanks.
1

If you want to get the results only with one query done on the background, without using with(), you can use fluent and join().

SELECT * FROM comments LEFT JOIN posts ON comments.post_id = posts.id

is equal to:

DB::table('comments')
    ->join('posts','comments.post_id','=','posts.id','left')
    ->get();

But I think also adding a groupBy() statement will give you better results:

Example:

DB::table('comments')
    ->join('posts','comments.post_id','=','posts.id','left')
    ->groupBy('comments.id')
    ->get();

But I'd prefer to use the other answer in my projects:

Comment::with('post')->get();

Comments

0

$comments:: all()->with ('post')->get()

4 Comments

::all() is not required if you're getting the collection like that. $comments::with('post')->get() is the correct usage
Unless I'm mistaken, this method also uses two database queries to retrieve the information (#1 for comment data and #2 for post data). Isn't there a way to retrieve it all using a single query?
@matt You will need to use fluent and join() then. But @kaning 's approach is more laravelish.
Using with() DOES use one query. Not using with() and calling $comment->post later in execution triggers a 2nd query. See the docs on eager loading for more information.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.