Laravel渴求式加載(比較容易理解理解load與with關系)


渴求式加載

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM