渴求式載入

當以屬性方式訪問 Eloquent關聯關係的時候,關聯關係資料是「懶惰式載入」的,這意味著關聯關係資料直到第一次訪問的時候才被載入。不過,Eloquent 還可以在查詢父級模型的同時「渴求式載入」關聯關係。渴求式載入緩解 N+1 查詢問題,要闡明 N+1 查詢問題,檢視關聯到 Auth的 Book模型:

Laravel學院文件: https://laravelacademy.org/post/9584.html

根據官方文件, 建立兩個表,不多說.

新建兩個model模型

php artisan make:model Auth
php artisan mkae:model Book

然後建立對應的表關聯關係

<?php
namespace App; use Illuminate\Database\Eloquent\Model; class Book extends Model
{
protected $table = 'book'; public function auth()
{
return $this->belongsTo('App\Auth');
}
}

在控制器中獲取書的作者資訊

  public function lst()
{
$books = Book::all(); foreach ($books as $book){
echo $book->auth->name;
}
}

去頁面檢視輸出資訊和SQL語句

這裡發現 其實這裡是執行了5條sql語句,在foreach迴圈中,每一次都執行了一條sql語句

文件中的解釋:

該迴圈先執行 1 次查詢獲取表中的所有書,然後另一個查詢獲取每一本書的作者,因此,如果有25本書,要執行26次查詢:1次是獲取書本身,剩下的25次查詢是為每一本書獲取其作者。
在這裡 我們使用渴求式載入. 當查詢的時候,可以使用 with方法指定應該被渴求式載入的關聯關係:

 public function lst()
{
$books = Book::with('auth')->get(); foreach ($books as $book){
echo $book->auth->name;
}
}

檢視輸出結果,發現,效果一樣,但原本執行的多條sql 變成了兩條

渴求式載入多個關聯關係

有時候你需要在單個操作中渴求式載入多個不同的關聯關係。要實現這個功能,只需要新增額外的引數到with方法即可:

在這裡,我又新建了一個category表

在Book模型中又加了一個與category表的關聯關係

public function category()
{
//這裡我在book表中與category表關聯的外來鍵欄位是cate_id,而laravel中預設是category_id,所以修改第二個引數為cate_id
return $this->belongsTo('App\Category','cate_id');
}

修改程式碼

 public function lst()
{
$books = Book::with('auth','category')->get(); foreach ($books as $book){
echo $book->category->name;
echo $book->auth->name;
}
}

檢視頁面輸出結果,這裡將category表中的資料也查出來了

巢狀的渴求式載入

要渴求式載入巢狀的關聯關係,可以使用”.“語法。例如,我們在一個 Eloquent 語句中渴求式載入所有書的作者及所有作者的個人聯絡方式:
$books = Book::with('auth.contact')->get();

這裡還需要新建一個contact表,存放作者的聯絡方式

然後新建一個Contact模型,並在Auth模型中關聯上Contact模型

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Auth extends Model
{
protected $table = 'auth'; public function contact()
{
return $this->belongsTo('App\Contact');
}
}

然後修改控制器中的程式碼

public function lst()
{
//通過 . 點號 來載入auth模型的contact關聯表
$books = Book::with('auth.contact')->get(); echo '<pre>'; foreach ($books as $book){
echo $book->name;
echo '<br/>';
echo $book->auth->name;
echo '<br/>';
echo $book->auth->contact->email;
echo '<hr/>';
}
}

檢視頁面輸出資訊,這裡將auth關聯的contact表的資訊也查出來了.

渴求式載入指定欄位

並不是每次獲取關聯關係時都需要所有欄位,因此,Eloquent 允許你在關聯查詢時指定要查詢的欄位:

$users = Book::with('auth:id,name')->get();

注:使用這個特性時,id欄位是必須列出的。

public function lst()
{
$books = Book::with('auth:id,name')->get()->toArray();
dd($books);
}

檢視頁面輸出程式碼 auth下只有id和name兩個欄位了 其他多餘的欄位都沒有了


帶條件約束的渴求式載入

有時候我們希望渴求式載入一個關聯關係,但還想為渴求式載入指定更多的查詢條件:

$books = Book::with(['auth' => function ($query) {
//約束條件
$query->where('name', 'like', '吳%');
}])->get();
dd($books);

檢視頁面輸出資訊,只有auth表中name欄位以吳開頭的資訊查出來了,其他的都沒查出來

在這個例子中,Eloquent 只渴求式載入 name 以吳開頭 的作者。當然,你還可以呼叫其它查詢構建器來自定義渴求式載入操作:

$books = Book::with(['auth' => function ($query) {
$query->orderBy('name', 'desc');
}])->get();

懶惰渴求式載入

有時候你需要在父模型已經被獲取後渴求式載入一個關聯關係。例如,這在你需要動態決定是否載入關聯模型時可能很有用:

$books  =  Book::all();
$res = true;
if($res){
$books->load('auth','category');
}
dd(collect($books)->toArray());

如果你需要設定更多的查詢條件到渴求式載入查詢上,可以傳遞一個包含你想要記載的關聯關係陣列到 load 方法,陣列的值應該是接收查詢例項的閉包:

$books->load(['auth' => function ($query) {
$query->orderBy('name', 'asc');
}]);

如果想要在關係管理尚未被載入的情況下載入它,可以使用 loadMissing 方法:

public function lst(Book $book)
{
$book->loadMissing('auth'); return [
'name' => $book->name,
'auth' => $book->auth->name
];
}

最後這個…試了很久,在大佬的幫助下完成了.
直接從文件複製過來就報錯了!!!坑啊
需要在路由那傳遞一個id

Route::get('book/{id}','ArticleController@lst');


去掉loadMissing之後…下面那行sql語句變了,但是感覺沒啥用啊.不知道這個東西有什麼用.

原文:https://blog.csdn.net/u013032345/article/details/82772938