Skip to content
Advertisement

Laravel 6.x – hasMany , belongsTo, when are the database queries for these executed?

I am a bit curious about the performance of my app. Therefore I just want to know that when the queries for the hasMany and belongsTo are executed?

Here is the relevant sample code for example:

class Article extends Model
{
    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

class User extends Authenticatable
{

    public function articles()
    {
        return $this->hasMany(Article::class);
    }
}

If I fetch all the user with:

$user = AppUser::find(1);

Now if I need the articles for this user, I would do it like this:

$user->articles;

This in the backend in Laravel executes the following query:

SELECT * FROM articles WHERE user_id = 1

and it will give me all the articles for the user. So far so good. But in most scenarios, I will just need the information of the user and would not want Laravel to execute that query for getting articles of the user. The same I need for the belongsTo.

My Question is, does laravel execute the query for articles at the time when I execute the query for User? or it executes the query at the time when I call:

$user->articles;

This is just an example scenario. I have many real world scenarios where one model has relationship with many other models. So here if I fetech all users with:

$users = AppUser::all();

Will it execute that articles query for all users one by one? or at once? and at what time does it query for the articles? if I do not call:

$user->articles;

does it still query database for articles of the user?

Update

So after some efforts I found out that when you query a user/users:

$user = AppUser::find(1);

it does not get the articles for the user until you call articles on it:

$user->articles;

But now there is another problem. If I am fetching all users and I also need the articles for each of them, I will have to do something like this:

$users = AppUser::all();

and then in a loop I will get the articles for each of the users, and the articles query will be executed for each user separately. Which is still a performance concern. If there are 100 users so I will have to query users table once with all() method and then 100 queries for articles of each user. Which is not what I want. I need one query for users and one query for articles. Once the articles for all users have been brought then the relevant articles should be assigned to each user.

But it seems like there is no such thing in Laravel. I will have to get user_ids of all the users and make a query like this:

$articles = AppArticle::whereIn("user_id", $user_ids_array)->get();

Then I will have to loop through the articles and assign each user their articles. I just wanted to find a short way using Laravel. But it seems like that is not possible for now. I wish if this would be available in future versions of Laravel.

Advertisement

Answer

You need to read more about Eager-loading in Laravel. In your case, you need to do :

$users = AppUser::with('articles')->get();

The “with” method is here exactly for this.

Another alternative to get all articles after your initial query call is this :

$users = AppUser::get();
$users->load('articles');

Of course, this is implying you have a working relationship and a “public function articles() {}” in your User Model. Probably something like this :

public function articles() {
  return $this->hasMany(Article::class);
}

You can read more about this feature here : https://laravel.com/docs/6.x/eloquent-relationships#eager-loading

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement