Стремительная загрузка по запросу laravel при глубокой вложенности 3 - PullRequest
0 голосов
/ 22 февраля 2020

У меня есть рабочие места и проекты на моем Laravel сайте, и между ними есть отношения. Я пытаюсь уменьшить количество сделанных запросов (и помнить о проблеме N + 1). Я делаю это с энергичной загрузкой в ​​моем контроллере при выводе моих JobItems.

Как я могу сделать это, когда я вкладываю: JobItems> Project> JobItems.

В одном случае это происходит, и я Я получаю повторяющиеся запросы. Я не уверен, как стремиться загрузить. Я обрисую ситуацию следующим образом:

Каждый JobItem имеет столбец для часов.

В моем проекте я СУММАЮ все связанные часы JobItem, чтобы определить общее количество часов в проекте. (Например, 3 JobItems по 4 часа каждый, в моей модели проекта есть аксессор, который говорит, что projectHours = 12).

  • job
    • project
      • project_hours (Сумма связанных заданий)

Я хочу перечислить все JobItems и каждый JobItem, чтобы иметь дочерний элемент соответствующего Project.

Итак, я звоню:

  1. Модель JobItem
  2. Модель проекта (для дочернего элемента в JobItem)
  3. Модель JobItem (для расчета общее количество часов в модели проекта)

На этом шаге 3 я получаю проблему N + 1 и несколько повторяющихся запросов. Я хотел бы уменьшить это с энергичной загрузкой, но не уверен, как, если я (на шаге 1) уже вызываю модель JobItem.

В моем контроллере у меня есть:

    public function getJobItems()
    {

        $userId = auth()->user()->id;

        return JobItem::whereHas('project', function ($query) use ($userId) {
            $query->where('user_id', '=', $userId);
        })->with(['project', 'user'])
            ->get();
    }

В моей модели проекта у меня есть:

class Project extends Model
{

    protected $appends = ['projectHours'];


    public function jobs()
    {
        return $this->hasMany('App\JobItem', 'project_id', 'id');
    }

    public function getProjectHoursAttribute()
    {
        return $this->jobs->sum('hours');
    }

}

Как всегда, если я подхожу к этому неправильно, дайте мне знать. Очень ценится.

NB. Это связано с этой заявкой SO о сокращении запросов с помощью Eager Loading: Как использовать нетерпеливую загрузку на Laravel модели с SUM отношения - в настоящее время получают несколько запросов (N + 1)

1 Ответ

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

Я собираюсь ответить на это в двух частях:


1) Предварительная загрузка отношений

Так что если вы попытаетесь перечислить jobItem collection, но для отображения атрибута, связанного с каждым элементом Project Job s, вы можете предварительно загрузить необходимые отношения следующим образом:

JobItem::with(['project.jobs'])->get();

Оператор . может использоваться для доступа вложенные отношения. (Это соответствует тем же правилам, что и при загрузке любых отношений, так как это название отношений в соответствующей модели)


2) Доступ к отношениям

Я заметил что вы ограничиваете запрос идентификатором пользователя, даже если у вас есть модель User. Если у вас есть jobItems отношения на вашей User модели, вы можете сделать это вместо этого:

public function getJobItems()
{
    $user = auth()->user()->loadMissing(['jobItems.project.jobs']);

    return $user->jobItems;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...