Laravel Eloquent关系效率

时间:2018-02-21 19:09:54

标签: laravel eloquent relationship

当我在模型中声明关系时,例如:

class Post extends Model
{
    public function comments()
    {
        return $this->hasMany(Comment::class);
    }
}

当我检索Post实例或我写的那一刻

时,是否从数据库中检索了注释
$post->comments;

3 个答案:

答案 0 :(得分:1)

答案很简单:

   $post->comments() returns the relationship object

   $post->comments returns the result of the relationship

所以当你执行$post->comments这意味着获取关系并执行查询时,就会返回关系数据库结果。

答案 1 :(得分:1)

当你提出要求时会检索它们,即$post->comments。如果您想加载它们,可以写Post::with('comments')->get()。查看documentation。它解释了急切的加载和N + 1问题。

来自文档:

  

当访问Eloquent关系作为属性时,关系数据是"延迟加载"。这意味着在您首次访问该属性之前,实际上不会加载关系数据。然而,Eloquent可以“急切地”加载"查询父模型时的关系。急切加载缓解了N + 1查询问题。

答案 2 :(得分:1)

到目前为止,答案已经解决了这个问题,但不是很清楚,所以请允许我帮忙。要直截了当地回答您的问题,创建Post实例 也会加载关联的comments

原因如下:

当您定义一个Eloquent关系时,您基本上会附加一个全新的查询'你的对象的方法,所以除非你打电话,否则它不会被实际执行。

作为一个简单示例,我们有Car

class Car {

    public $color;

    public function __construct() {
        $this->color = 'blue';  
    }

    public function makeRed() {
        $this->color = 'red';
        return $this;
    }
}

在此示例中,实例化的Car只有一个属性color。这辆车将为蓝色,除非您调用makeRed()方法并进行更改。它不同时计算两个选项,期望您可能决定更改它的颜色。

因此,为了将其与Eloquent关系相关联,comments方法返回一个关系对象,但前提是在Post对象上调用该方法。在此之前,您的Post对象不会自动调用它自己的方法。基本上,不要担心物体会因大量方法而变大,因为这些方法只有在实际调用时才会显着影响物体尺寸。

如果您希望comments立即加载Post,则急切加载初始查询将允许此操作:

$post = Post::with('comments')->findOrFail('post_id');

否则,以下内容将为您提供给定帖子的评论:

$post = Post::findOrFail('post_id');
$post->comments;

有关详细信息,请参阅Eager Loading上的Laravel文档。

希望这有帮助!