Устранение повторяющихся запросов с помощью Eager Loading

Я пытаюсь избавиться от ненужных запросов на своем сайте, но никак не могу разобраться с нетерпеливой загрузкой и отложенной загрузкой. У всех пользователей на моем сайте есть списки, а у списков есть несколько пользователей. Они связаны через таблицу listing_users. Каждый список имеет один «заказ», связанный с ним. Вот модель пользователя:

Модель пользователя:

public function listings(){
   return $this->belongsToMany(Listing::class)->withPivot('role_id');
}

Модель листинга:

  public function order(){
   return $this->hasOne(Order::class)->first();
  }

Моя текущая панель инструментов загружается путем вызова этого viewListings в UserController:

public function viewListings(){
  $user = Auth::user();
  $listings = $user->listings()->orderBy('created_at','desc')->get();
  return view('user.listings', compact('listings'));
}

Проблема возникает в моем лезвии просмотра user.listings, где у меня есть цикл foreach для каждого списка, а затем также вызывается каждый заказ. Мне нужен способ передать списки на страницу с соответствующими заказами.

  @foreach($listings as $listing)
    @if($listing->order()->status == 'completed')
      {{-- Display the listing details here --}}
    @endif
  @endforeach 

Будем признательны за любые советы в вышеописанной ситуации! Я уверен, что для этого есть простое решение Laravel, которое я упускаю из виду.


person bdweix    schedule 05.01.2018    source источник


Ответы (1)


Попробуй это:

Модель листинга:

public function order(){
  return $this->hasOne(Order::class); //without first()
}

UserController: здесь мы используем метод with('order') для быстрой загрузки Order модели для каждой Listing модели, полученной по запросу. Так что теперь в вашем блэйде не будет лишних запросов.

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

public function viewListings(){
  $user = Auth::user();
  $listings = $user->listings()->orderBy('created_at','desc')
  ->with('order')->get();//added with('order')
  return view('user.listings', compact('listings'));
}

user.listings: вы должны использовать order без (), если вам нужно получить свою модель. Поэтому, если вы хотите изменить order, используйте его с () в качестве построителя запросов и добавьте дополнительные ограничения, такие как where, orderBy и т. д., и в конце добавьте first(). Здесь вы можете понять, почему мы удалили first() из hasOne выше.

@foreach($listings as $listing)
   @if($listing->order->status == 'completed')
    {{-- order instead of order() --}} 
     {{-- Display the listing details here --}}
   @endif
@endforeach 
person yrv16    schedule 05.01.2018
comment
Хотя это должно сработать, это было бы очень полезно для ОП и других, пытающихся объяснить, что вы делаете и почему это решает проблемы. - person patricus; 06.01.2018