• 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 IlluminateDatabaseEloquentModel;
    
    class Book extends Model
    {
        protected  $table = 'book';
    
    	
        public function auth()
        {
            return $this->belongsTo('AppAuth');
        }
    }
    

    在控制器中获取书的作者信息

      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('AppCategory','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 IlluminateDatabaseEloquentModel;
    
    class Auth extends Model
    {
        protected $table = 'auth';
    
        public function contact()
        {
            return $this->belongsTo('AppContact');
        }
    }
    

    然后修改控制器中的代码

    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

  • 相关阅读:
    Json对象和Json字符串
    主界面的构造函数报错
    WPF DataGrid绑定的数据源更新后界面信息不更新
    WPF 数据绑定 ( 经验 )
    WPF 简单快速地去掉Button控件的边框
    字节数组与字符串形式的数字(序列号)之间的相互转换
    将十进制数字转换为字节数组
    WPF 调用线程无法访问此对象,因为另一个线程拥有该对象。
    cmd中一些命令
    Notepad++运行快捷键的设置
  • 原文地址:https://www.cnblogs.com/lxwphp/p/10727259.html
Copyright © 2020-2023  润新知