กำจัดข้อความค้นหาที่ซ้ำกันด้วย Eager Loading

ฉันกำลังพยายามกำจัดคำค้นหาที่ไม่จำเป็นบนเว็บไซต์ของฉัน แต่กำลังดิ้นรนเพื่อจัดการกับ Eager Loading และ Lazy Loading ผู้ใช้ทั้งหมดบนไซต์ของฉันมีรายชื่อ และรายชื่อมีผู้ใช้หลายคน พวกเขาเชื่อมต่อกันผ่านตาราง list_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'));
}

ปัญหาเกิดขึ้นใน blade view user.listings ของฉัน โดยที่ฉันมี foreach loop สำหรับทุกรายการ จากนั้นจึงเรียกแต่ละคำสั่งซื้อเช่นกัน ฉันต้องการวิธีส่งรายการไปยังเพจพร้อมคำสั่งซื้อที่เกี่ยวข้อง

  @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()
}

ตัวควบคุมผู้ใช้: ที่นี่เราใช้เมธอด with('order') สำหรับการโหลดโมเดล Order สำหรับแต่ละโมเดล Listing ที่ดึงข้อมูลโดยการสืบค้น ดังนั้นตอนนี้ในเบลดของคุณจะไม่มีการสืบค้นที่ไม่จำเป็นอีกต่อไป

เมื่อเข้าถึงความสัมพันธ์ Eloquent เป็นคุณสมบัติ ข้อมูลความสัมพันธ์จะเป็น "การโหลดแบบ Lazy Load" ซึ่งหมายความว่าข้อมูลความสัมพันธ์จะไม่ถูกโหลดจริง ๆ จนกว่าคุณจะเข้าถึงคุณสมบัติเป็นครั้งแรก อย่างไรก็ตาม 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
แม้ว่าสิ่งนี้ควรจะได้ผล แต่จะมีประโยชน์มากสำหรับ OP และผู้อื่นที่กำลังค้นหาเพื่ออธิบายว่าคุณกำลังทำอะไรอยู่และทำไมจึงแก้ไขปัญหาได้ - person patricus; 06.01.2018