Laravel Автоматическое отключение Eloquent c Жадная загрузка - PullRequest
2 голосов
/ 20 февраля 2020

Laravel по умолчанию имеет эту автоматическую c нетерпеливую загрузку, которая может вызвать проблему с несколькими запросами. Например:

// If do something like this
$posts = Post::published()->get();
// then
foreach ($posts as $p) {
    echo $p->author->name;
}
// Eloquent will query the author for every post

Возможно ли отключить это поведение?

Ответы [ 2 ]

4 голосов
/ 20 февраля 2020

В приведенном вами примере данные отношений «загружаются лениво», а не «загружены нетерпеливо». Это означает, что данные отношения фактически не загружаются, пока вы не получите первый доступ к свойству.

Однако Eloquent может «загружать» отношения во время запроса родительской модели. Стремительная загрузка облегчает проблему запроса N + 1.

Чтобы загружать отношения, вы можете использовать eloquent with() метод:

$posts = Post::published()->with('author')->get();

Теперь каждый post будет загружен с помощью модели author, таким образом, избегая N + 1 проблема.

Вы также можете указать, хотите ли вы активировать загрузку только для указанных c столбцов:

$posts = Post::published()->with('author:id,name')->get();

И хотите ли вы всегда загружать отношения при получении модели Вы можете определить $ со свойством для модели:

class Post extends Model
{
    /**
     * The relationships that should always be loaded.
     *
     * @var array
     */
    protected $with = ['author'];

    /**
     * Get the author that wrote the book.
     */
    public function author()
    {
        return $this->belongsTo('App\Author');
    }
}

Дополнительная информация: https://laravel.com/docs/6.x/eloquent-relationships#eager -загрузка

1 голос
/ 20 февраля 2020

Лениво загрузить пример, который вы указали как @LobsterBaz. Если вы хотите избежать этого:

Вы можете проверить, загружены ли отношения

foreach ($posts as $p) { 
    if ($p->relationLoaded('author')) echo $p->author->name; 
}

Но я нашел этот пакет Laravel Отключить Lazy Load , который имеет все кредит за идею.

Это очень просто. Заимствуя идею, вы можете создать черту самостоятельно, чтобы переопределить getRelationshipFromMethod .

<?php

namespace App\Traits;


trait DisableLazyLoad
{
    public function getRelationshipFromMethod($method)
    {
        throw new \BadMethodCallException('Relation lazy load has been disabled for performance reasons.');
    }
}

Затем использовать черту в вашей модели

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use App\Traits\DisableLazyLoad;

class Post extends Model
{

    use DisableLazyLoad;

}

или установить пакет использовать его таким же образом

composer require ybaruchel/laravel-disable-lazyload
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...