Laravel - Eloquent «отношение» отправить запрос только один раз - PullRequest
0 голосов
/ 09 июля 2019

Я заметил странное поведение при использовании красноречивого отношения.

Я написал этот простой тест:

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 голосов
/ 09 июля 2019

После загрузки Laravel кэширует значения отношений, поскольку в большинстве случаев не требуется перезагрузка при каждом обращении к свойству.

Если вы хотите принудительно перезагрузить отношения, вы можете вызвать $book->load('position')

0 голосов
/ 09 июля 2019

В 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');
0 голосов
/ 09 июля 2019

Вы инициализируете

$couny_end   = 3;

, но используете $count_end вместо этого в for:

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

$count_end ложно и после первой итерации $position не будетдольше быть false.

...