thinkphp5 关联预载入 with 单个关联与多个嵌套关联

前面的是官方的内容,下方有一些自己的使用案例

关联预载入功能有大大缩小查询次数

例如下面的查询如果有3个记录,会执行4次查询:

$list = User::all([1,2,3]);
foreach($list as $user){
    // 获取用户关联的profile模型数据
    dump($user->profile);
}

如果使用关联预查询功能,对于一对一关联来说,只有一次查询,对于一对多关联的话,就可以变成2次查询,有效提高性能。

$list = User::with('profile')->select([1,2,3]);
foreach($list as $user){
    // 获取用户关联的profile模型数据
    dump($user->profile);
}

支持预载入多个关联

例如:
$list = User::with('profile,book')->select([1,2,3]);

也可以支持嵌套预载入,例如:
$list = User::with('profile.phone')->select([1,2,3]);
foreach($list as $user){
    // 获取用户关联的phone模型
    dump($user->profile->phone);
}

延迟预载入(V5.0.5+)

有些情况下,需要根据查询出来的数据来决定是否需要使用关联预载入,当然关联查询本身就能解决这个问题,因为关联查询是惰性的,不过用预载入的理由也很明显,性能具有优势。

延迟预载入仅针对多个数据的查询,因为单个数据的查询用延迟预载入和关联惰性查询没有任何区别,所以不需要使用延迟预载入。

如果你的数据集查询返回的是数据集对象,可以使用调用数据集对象的load实现延迟预载入:
// 查询数据集
$list = User::all([1,2,3]);
// 延迟预载入
$list->load('cards');
foreach($list as $user){
    // 获取用户关联的card模型数据
    dump($user->cards);
}

如果你的数据集查询返回的是数组,系统提供了一个load_relation助手函数可以完成同样的功能。
// 查询数据集
$list = User::all([1,2,3]);
// 延迟预载入
$list = load_relation($list,'cards');
foreach($list as $user){
    // 获取用户关联的card模型数据
    dump($user->cards);
}

一个关联预加载的例子

先放用到的表的内容

banner表
thinkphp5 关联预载入 with 单个关联与多个嵌套关联
banner_item表
thinkphp5 关联预载入 with 单个关联与多个嵌套关联
image表
thinkphp5 关联预载入 with 单个关联与多个嵌套关联


我们定义了BannerBanneritem两个模型,Banner中有内容,Banneritem
作用便是

Banner模型内容

<?php
namespace app\api\model;
use think\Model;
use think\Db;
use think\Exception;

class Banner extends Model
{
    public function items()
    {
        return $this->hasMany('BannerItem','banner_id','id');
    }

banner方法中代码

$banner = Banner::with('items')->find($id);
方法的全部代码
<?php
namespace app\api\controller\v1;
use think\Controller;
use app\api\validate\IDMustBePostiveInt;
use app\api\model\Banner as BannerM;
use app\lib\exception\BannerMissException;
class Banner extends Controller
{
    /**
     * 获取指定id的banner信息
     * @url /banner/:id
     * @http GET
     * @id banner的id号
     */
    public function getBanner($id)
    {
        (new IDMustBePostiveInt())->goCheck();

        $banner = BannerM::with('items')->find($id);

        if(!$banner){
            throw new BannerMissException();
        }
        return json($banner);

    }
}

输出$banner便可将两个表查询的内容全部查询出来,可以看出items以一个数组的形式存在
输出结果
thinkphp5 关联预载入 with 单个关联与多个嵌套关联

多个关联共同查询

上面是我们只定义了一条关联查询,但很多时候我们需要定义多个关联共同使用,下面便是一个两个关联共同使用的例子
我们新建一个Image模型,内容为空即可
在Banneritem模型中增加关联内容

Banneritem代码

我们采用一对一的关联方式
<?php
namespace app\api\model;
use think\Model;
use think\Db;
use think\Exception;

class BannerItem extends Model
{
    public function img()
    {
        return $this->belongsTo('Image','img_id','id');
    }
}
方法中使用时稍作修改
$banner = BannerM::with(['items','items.img'])->find($id);
因为要使用两个关联模型,所以采用了数组的方式
items.img的理解
虽然Img是一个独立的关联模型,但当多个关联模型在一起使用时,我们必须用.对多个关联进行连接,若是写成with(['items','img'])会出错,且这样连接后,在输出时img会成为items数组中的一个下维数组
输出后的结果
thinkphp5 关联预载入 with 单个关联与多个嵌套关联
如上面所说,可以看到items数组中多了一个叫img数组的下维数组,里面的内容便是image表的内容

将查询语句放入模型中

$banner = BannerM::with(['items','items.img'])->find($id);
上面这条语句,目前在方法之中,但查询语句更有适合在Banner模型中,所以我们将其移入模型里面
在Banner模型中新增
public static function getBannerById($id)
    {
        $banner = self::with(['items','items.img'])->find($id);
        return $banner;
在方法文件中使用
$banner = BannerM::getBannerById($id);


评论

大侠名号:   验证暗号: 点击我更换图片

修远兮

在这里记录每一点自己需要的知识

添加创始人微信,一起交流心得

推荐文章RECOMMEND