douchun1900 2016-01-06 05:24
浏览 30
已采纳

Laravel 5:默认情况下Eloquent急切加载吗?

I got this structure:

School -> hasMany -> Classes

So when I tried the codes below via artisan tinker

App\School::with('schoolclasses')->find(2283)->schoolclasses;

I can get the classes without problem.

But when I tried without the with I still get the same result without problem:

App\School::find(2283)->schoolclasses;

Does Eloquent eager loads by default? If so, how to disable it?

  • 写回答

2条回答 默认 最新

  • douchun1859 2016-01-06 08:12
    关注

    No, Laravel does not eager load by default. Lets take this step by step. Lets ignore ->schoolclasses; for a moment.

    App\School::with('schoolclasses')->find(2283);
    

    This will query the database twice. First, it will get the School with a primary key of 2283. Then, it will immediately query the database and get all the related schoolclasses.

    App\School::find(2283);
    

    This will only query the database once. It will only get the School. There is no eager loading done so far. If you debug and keep track of your database queries, you will see that this will only query the database once while eager loading will query it twice.

    When you try to access the schoolclasses by doing ->schoolclasses;, everything actually works. So why do you get the same results? It is a bit deceptive, but it's not the same. When you try to access the schoolclasses, Laravel will check if it has already been eager loaded. If so, it will return the collection of schoolclasses. No querying is done. It just immediately returns them. However, if you did not eager load them, Laravel will query the database on the spot and get the schoolclasses. Ultimately, for this particular example, you get the same results, but when you query the database is different.

    However, this is actually a poor example of the main benefit to eager loading.

    The main benefit of eager loading is to alleviate the N + 1 query problem. Lets say you want to get 5 schools and all of its classes. Without eager loading, this is what you would do:

    $schools = School::take(5)->get();
    
    foreach ($schools as $school)
    {
        $schoolclasses = $school->schoolclasses;
    }
    

    That is a total of 6 queries for such a simple task. I added comments below to understand where the queries are coming from:

    $schools = School::take(5)->get(); // First query
    
    foreach ($schools as $school)
    {
        // For each school, you are querying the database again to get its related classes.
        // 5 schools = 5 more queries
        $schoolclasses = $school->schoolclasses;
    }
    

    However, if you eager load everything, you only have two queries:

    // Two queries here that fetches everything
    $schools = School::with('schoolclasses')->take(5)->get();
    
    foreach ($schools as $school)
    {
        // No more queries are done to get the classes because
        // they have already been eager loaded
        $schoolclasses = $school->schoolclasses;
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 metadata提取的PDF元数据,如何转换为一个Excel
  • ¥15 关于arduino编程toCharArray()函数的使用
  • ¥100 vc++混合CEF采用CLR方式编译报错
  • ¥15 coze 的插件输入飞书多维表格 app_token 后一直显示错误,如何解决?
  • ¥15 vite+vue3+plyr播放本地public文件夹下视频无法加载
  • ¥15 c#逐行读取txt文本,但是每一行里面数据之间空格数量不同
  • ¥50 如何openEuler 22.03上安装配置drbd
  • ¥20 ING91680C BLE5.3 芯片怎么实现串口收发数据
  • ¥15 无线连接树莓派,无法执行update,如何解决?(相关搜索:软件下载)
  • ¥15 Windows11, backspace, enter, space键失灵