[laravel 5.4] Eloquent: Querying Relations การคิวรี่ข้อมูลแบบ Relations

21 ส.ค. 2017 , 6,842 Views   , หมวดหมู่ Laravel ทุกหมวดหมู่ โค๊ดดิ้ง   , ป้ายกำกับ:


ยกตัวอย่างการเข้าถึง Post Model ผ่าน User Model

สามารถเข้าถึงและฟิวด์เตอร์ข้อมูลต่างๆได้

สามารถใช้  query builder ใน Eloquent: Relationships ได้

Querying Relationship Existence

ตัวอย่างเช่น สมมติว่าคุณต้องการเรียกใช้บทความบล็อกทั้งหมดที่มีความคิดเห็นอย่างน้อยหนึ่งความคิดเห็น เป็นต้น

สามารถใช้ operator ได้

ต้องการบทความทั้งหมดที่มีความคิดเห็นอย่างน้อยหนึ่งความคิดเห็นและมีโหวตด้วย

นอกจากนี้หากต้องการฟิวเตอร์ข้อมูลมากกว่านั้นยังสามารถใช้ whereHas และ orWhereHas ตัวอย่างข้างล่างคือ ต้องการบทความทั้งหมดที่ใน content ของ comment ขึ้นต้นด้วย foo

Querying Relationship Absence

ต้องการบทความทั้งหมดที่ไม่มีความคิดเห็น

ต้องการบทความทั้งหมดที่ในความคิดเห็นฟิวด์ content ไม่ได้ขึ้นต้นด้วย foo

Counting Related Models

นับจำนวนผลการค้นหาจากความสัมพันธ์โดยไม่ต้องโหลดข้อมูลจริง ให้ใช้ withCount  และใช้ฟิวด์ชื่อ {relation}_count  เป็น Column ในการแสดงผลข้อมูล

นับผลการค้นหาจากหลายๆความสัมพันธ์

นับผลการค้นหาได้หลายครั้งจากความสัมพันธ์เดียว

Eager Loading

คือการจัดการๆปัญหาการคิวรี้แบบลูกโซ่ ตัวอย่างข้างล่าง หนังสือมีผู้แต่งได้หลายคน

Book Model

ทำการดึงข้อมูลชื่อผู้แต่ง

เมื่อทำการคิวรี่ก็จะมีการคิวรี่เกิดขึ้นหลายครั้งเพราะหนังสือแต่ละเล่มก็จะไปค้นหา ผู้แต่งของมันด้วย ซึ่งจะทำให้ช้ามาก แต่ Laravel ก็เตรียมฟังก์ชัน with ไว้ให้แล้วครับ

ถ้าเราใช้ฟังก์ชัน with จะมีการคิวรี่แค่สองครั้งตามข้างล่างนี้เลยครับ

ใช้กับหลายๆความสัมพันธ์

นอกจากนี้ยังสามารถใช้ query builder เพื่อโหลดเฉพาะ posts ที่ต้องการได้

ตัวอย่างการใช้ ไปสอบถามในกลุ่ม Laravel Thailand มา มีพี่ๆใจดีมาตอบครับ

คำถาม

สอบถามเรื่อง Eager loading ครับ เพื่อความแน่ใจ
คือผมมีตาราง Car กับตาราง User
ซึ่ง User 1 คนสามารถสร้าง Car ได้หลาย Car
และ Car สามารถมี User ได้แค่ 1 คน

ใน CarController ผมต้องใช้ with ไหมครับ
$results = Car::with(‘user’)

หรือจะใช้ก็ต่อเมื่ออยู่ใน UserController
$results = User::with(‘car’)

แล้ว Eager loading นี้ใช้ในกรณีไหนบ้างครับ ตอนนี้ผมเข้าใจว่าใช้ทุกกรณีที่ Model มี Relation ผมเข้าใจถูกไหม

คำตอบ

กรณีที่ 1 ในหน้า show user 1 คน
เราต้องการให้หน้าที่แสดง user และ cars ทั้งหมดของ users นั้น อันนี้ไม่จำเป็นต้อง eager load ครับ เพราะลงท้ายแล้วจะมี 2 query อยู่ดีคือ เรียก user กับเอา user_id ไปหา cars

กรณีที่ 2 ในหน้า list user ทั้งหมด (อาจจะ 10 คน หรืออะไรก็ว่าไป)
โดยในหน้านี้ สมมุติว่าเราต้องการให้มันแสดง cars ทั้งหมดด้วย code ประมาณ
@foreach($users as $user)
{{ $user->name }}
<ul>
@foreach($user->cars as $car)
<li>{{$car->model }}</li>
@endforeach
</ul>
@endforeach
ในกรณี จะเห็นว่า ใน loop มีการเรียกใช้ $user->cars ซึ่งถ้าผ่านบรรทัดนี้ 1 ครั้งมันจะ query หา cars ทั้งหมดของ user นั้น 1 ที
ถ้าสมมุติหน้านั้นแสดง 10 user จะใช้ทั้งหมด 1(เรียก user) + 10 (เรียก cars ของแต่ละ user)
ในกรณีนี้สมควรใช้ eager load เพื่อลด query โดยอาจจะใช้ ->load หรือ ->with ก็ได้ แล้วแต่่าใช้กับ collection หรือ query builder

กรณีที่ 3 ในหน้า show user 1 คน
เราต้องการให้หน้าที่แสดง user และ cars ทั้งหมดของ users นั้น เหมือนอันแรก แต่บังเอิญว่า รถแต่ละคัน มันดันมีความสัมพันธ์กับตารางประกันประกัน และเราต้องการแสดงประกันด้วย ประมาณนี้
{{ $user->name }}
<ul>
@foreach($user->cars as $car)
<li>{{$car->model }} {{ $car->insurane->name }}</li>
@endforeach
</ul>
อันนี้จำคล้ายกรณีที่ 2 คือมันผ่าน $car->insurane หลายรอบ แต่ละรอบคือ 1 query ดังนั้นอันนี้ก็ควรต้อง eager load เช้นกัน

 

ที่มา
https://laravel.com/docs/5.4/eloquent-relationships#querying-relations
http://www.thaicreate.com/community/laravel-eloquent-orm-model-part.html

http://www.qsbg.org/BGOaudit/file/1.pdf


ป้ายกำกับ: