渴求式加載
當以屬性方式訪問 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