Laravel-雄辩的“关系”仅提交查询一次

时间:2019-07-09 13:26:50

标签: laravel laravel-5 eloquent relation

我通过雄辩的关系发现一种奇怪的行为。

我写了这个简单的测试:

Route::get('/myTest', function () {
    $book = \App\Models\BookModel::findOrFail(7);

    $count_start = 1;
    $count_end   = 3;
    while ($count_start <= $count_end) {
        \Log::info('  A');
        $position = $book->position->name;
        \Log::info('  B');
        sleep(5);
        $count_start++;
    }    
});

日志转发:

[2019-07-09 13:40:04] - INFO:   A
[2019-07-09 13:40:04] - DEBUG:  query: {"sql":"select * from `position` where `position`.`fk_book` = ? limit 1","time":4.66,"bindings":[7]}
[2019-07-09 13:40:04] - INFO:   B
[2019-07-09 13:40:09] - INFO:   A
[2019-07-09 13:40:09] - INFO:   B
[2019-07-09 13:40:14] - INFO:   A
[2019-07-09 13:40:14] - INFO:   B

奇怪的行为是,该过程首次进入while时,查询被正确执行;第二次和第三次(5秒后)查询不再执行,我也不明白为什么!

这正常吗?为什么关系查询仅在第一次执行?

谢谢。

3 个答案:

答案 0 :(得分:0)

您初始化

$couny_end   = 3;

但在$count_end中使用for

while ($count_start <= $count_end && $position == false) {
    //...
}

$count_end是虚假的,并且在第一次迭代之后$position将不再是false

答案 1 :(得分:0)

一旦加载,Laravel将缓存关系值,因为大多数用例不需要每次访问该属性时都重新加载。

如果您想强制它重新加载关系,可以致电$book->load('position')

答案 2 :(得分:0)

在Laravel中,关系被缓存。

首次访问$book->position时,它会执行查询,因为还没有position模型。执行查询后,position模型将附加到$book对象。因此,随后对$book->position的每次调用都将使用该对象,而不会触发新的数据库查询。

这是默认的行为,但是您可以利用Laravel来完成所需的任何操作。

如果要在单个查询中加载具有关系的模型(对大量对象有用),可以急于加载它:

$book = BookModel::with('position')->findOrFail(7); // $book->position is immediately populated

如果需要在已缓存数据时强制执行新查询,则需要访问和查询关系:

$position = $book->position()->first(); // Force the execution of a new query

$book->load('position');