laravel 使用with预加载(渴求加载)的使用方法示例及嵌套查询示例

with()方法能做什么?在什么场景使用?

1.情景如下。2张数据表 主表userinfors用户表【id,name,created_at】,从表文章表articles表【id,user_id,title,content,created_at】
3.需求:根据当前登录用户A获取A所发布的文章。
4.模型之间的关系:一对多,一个用户能有多篇文章。

表结构

1.主表(userinfors)
在这里插入图片描述
2.从表(articles)
在这里插入图片描述

代码实现(根据当前登录用户,获取用户下的所有相关文章)

1.创建model(这里就不在赘述)
2.在主表model(userinfor表)模型中创建一对多关联关系

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Tests\Controllers\UserController;

/**
 * 前端用户模型
 * Class UserInfor
 * @package App\Models
 */
class UserInfor extends Model
{
    use HasFactory;

    //与模型关联的表名
    protected $table = 'userinfors';

    //不准批量复制的属性请填写在下放数组中
    protected $guarded = [];

    //模型序列化:Date 类型转换
    protected $casts = [
        'created_at' => 'date:Y-m-d H:i:s',
        'updated_at' => 'date:Y-m-d H:i:s',
    ];

    /**
     * 用户模型一对多关联用户动态表
     * 一个用户拥有多条的动态数据
     * 参数1:要关联的模型(从表)
     * 参数2:存在于从表中的那个与userinfor(主表)关联的字段
     * 参数3:存在于主表中的那个与 从表进行关联的字段名
     */
    public function article_hasMany()
    {
        return $this->hasMany(Article::class,'user_id','id');
    }

}

3.在控制器Controller中实现with

<?php

namespace App\Http\Controllers\Api\V1;

use App\Http\Controllers\BaseController;
use App\Http\Controllers\Controller;
use App\Models\Article;
use App\Models\UserInfor;
use Illuminate\Http\Request;

/**
 * 用户动态控制器
 * Class UserDynamicController
 * @package App\Http\Controllers\Api\V1
 */
class ArticleController extends Controller
{
   
    //获取当前登录用户动态列表
    public function getMyDynamicList(Request $request){
        //接收必要参数
        $page = $request['page'] ?? 1;//分页
        $limit = 2;//每页数据条数
        $offset = $page * $limit - $limit;//从第几条开始读取 默认为第0条
        //查询当前用户动态数据(倒序排列)
        $user_id = UserInfor::where('id',1);//获取当前登录的用户模型
        //查询当前用户下的文章,并进行分页,每页2条数据,按文章的创建时间进行倒序排列。
        $data_list = $user_id->with(['article_hasMany'=>function($query) use($offset,$limit){
        	//注意:在这个闭包里面的调用的字段均为被关联的model中的字段(也就是存在于从表中的字段,无需考虑从表字段名与主表字段名重复的问题。)
        	//如下面的示例:$query->orderBy('从表中的created_at','desc')->offset($offset)->limit($limit);
            $query->orderBy('created_at','desc')->offset($offset)->limit($limit);
        }])->first();
	
		dd($data_list->toArray());//laravel框架自带的打印函数,效果等同于下方2行代码。
        //var_dump($data_list->toArray());
        //die;
    }


}

4.返回数据结构

array:25 [
  "id" => 1
  "created_at" => null
  "name" => "刘通"
  "articles" => array:2 [
    0 => array:5 [
      "id" => 2
      "created_at" => "2020-10-26 10:36:59"
      "user_id" => 1
      "title" => "作家A-2"
      "content"=>"内容A-2内容A-2内容A-2内容A-2"
    ]
     1 => array:5 [
      "id" => 1
      "created_at" => "2020-10-22 12:36:59"
      "user_id" => 1
      "title" => "作家A-1"
      "content"=>"内容A-1内容A-1内容A-1内容A-1"
    ]
  ]
]

4.总结:
简单说下我为什么要用这个with()方法:这是因为他压缩了mysql查询语句,将查询语句变为2条。
第一条查指定用户。
第二条查所有的指定文章。
sql只跑了2遍。

而常规套路会跑N+1遍
第一遍查指定用户。
第二遍查指定文章。
第…查指定文章。
第N边查指定文章。
这样做对数据库不是很友好,缺点大家都明白,我不在赘述了。

5.实战代码

//获取当前登录用户动态列表
    public function getMyDynamicList(Request $request){
        //接收必要参数
        $page = $request['page'] ?? 1;//分页
        $limit = 12;//每页数据条数
        $offset = $page * $limit - $limit;//从第几条开始读取 默认为第0条
        //查询当前用户动态数据(倒序排列)
        $user_infor = UserInfor::where('token',$request['token']);
        $data_list = $user_infor->with(['userDynamics'=>function($query) use($offset,$limit){
            $query->orderBy('created_at','desc')->offset($offset)->limit($limit);
            $query->withCount('userDynamicComments as connent_count');//参数1,模型中的关联方法名,as * 表示返回值的别名
            $query->withCount('userDynamicAdmiress as admiress_count');
        }])->select('id','nickname','pic_url')->first();

    }

with循环嵌套用法

1.使用场景:当3张关联时想要循环嵌套应该怎么写。

举一个不恰当的例子!
假设情景:现有3张表分别为 A:书籍表,B:评论表,C:评论者电话表。
表关系:注意:同一本书只能被同一个人评论一次!(也就是一本书可以有多条评论,但每条评论的评论者只能和这本书产生一次关联!)
书籍表(一)对 评论表(多) = 一对多关联。
评论表(一) 对 评论者(一) = 一对一关联。
需求:已知书籍id指定评论id,现根据书籍id查询得出评论内容以及评论者电话数据
表结构图下:
A:书籍表(book)

idname(书籍名称)
1我的php文档
2我的加班历史
3我的工作记录

B:评论表(comment)

idcomment(评论内容)book_id(书记表关联id)tel_id(电话表关联id)
1这本书真的很厚118
2看的我眼睛都花了143
3这真的是日常记录吗?写的好详细269

C:评论者电话表(tel)

idcomment_id(评论表id)tel(评论者电话号码)
181183******3645
432133******2625
693131******1661

2.使用with()代码实现循环嵌套查询

//根据指定书籍id 与 指定评论id 获取当前书籍数据。
    public function getBookParticulars(Request $request){
        //接收书籍id
        $book_id = $request->book_id;//书籍id
        $comment_id = $request->comment_id;//指定评论id

        //bookComment = 书籍Book模型自定一对多关联评论方法的名称
        //commentTel = 评论内容表一对一关联评论者电话表
        $book = Book::where('id',$book_id)->with(['bookComment'=>function($query) use ($comment_id){
        	//$comment_id 前端传递给php方法的参数,需要use才能在with中使用
            $query->where('id',$comment_id)//这里的id指的是comment表中的id

                #->with('commentTel:id,tel')//嵌套写法A 这行代码中的‘id’是评论者电话表(tel)的id,不写这个id可能会导致没有查询结果
				//commentTel是评论对评论者的方法名
                ->with(['commentTel'=>function($query2){
                    $query2->first();
                }])//嵌套写法B

                ->first();
        }])->first();

        dd($book);//打印数据查看结果
    }
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值