欢迎来到元素模板ys720.com,本站提供专业的织梦模板PBOOTCMS模板网站模板网站修改/网站仿站
当前位置:主页 > 程序教程 > thinkphp教程 >
thinkphp教程

thinkphp5 Model模型如何关联查询返回指定字段

(元素模板) / 2024-03-20 14:50
thinkphp5 如何使用模型关联查询返回指定字段?

模型关联可以使用hasone/hasMany/belongsTo 这几种

原始代码如下
public static function getMessageListByPage($pageno, $rows)
    {
        $ruleList = [];
        //with 关联预载入
        $ruleList = collection(self::with('user')
        ->order('updatetime desc')
        ->page($pageno.','.$rows)
        ->field('uid, lastmessage, readstatus, file, appid')
        ->select())->toArray();
        return $ruleList;
    }
    //关联方法的使用
    //has_one(或has_many):外键在子关联对象中
    //belongs_to:外键在父联对象中
    //当有大量的关联数据需要查询的时候,一般都会考虑选择关联预载入的方式
    //预载入方法定义
    public function user()
    {
        // setEagerlyType设置预载入查询方式为 0 为 JOIN 1为 IN
        return $this->belongsTo('User', 'uid', 'id', [], 'LEFT')
        ->field('email')
        ->setEagerlyType(0);
    }
这是一个最新消息列表的分页查询,我想在每条消息上附带上用户邮箱,就是email字段
查询结果如下 :
[
    {
        "uid":45,
        "readstatus":0,
        "lastmessage":"0",
        "file":0,
        "createtime":0,
        "updatetime":0,
        "appid":0,
        "user":{
            "id":45,
            "group_id":3,
            "email":"xxxxxxxx@qq.com",
            "password":"xxxxxxxxxxxxx",
            "xxx":"xxxx"
        }
    }
]
虽然成功带上了email 字段,但是却是在user 属性里面,并且整个查询把user 表的所有字段都返回了,field方法对belongsTo 关联不起作用.这肯定不符合我的预期啊
 
于是乎遇事不决看文档,文档说可以使用bind()方法指定查询字段,该方法支持数组,以下为官方文档:
 
绑定属性到父模型(V5.0.4+)
可以在定义关联的时候使用bind方法绑定属性到父模型,例如:
<?php
namespace app\index\model;

use think\Model;

class User extends Model 
{
    public function profile()
    {
        return $this->hasOne('Profile','uid')->bind('nickname,email');
    }
}
//或者使用数组的方式指定绑定属性别名
<?php
namespace app\index\model;

use think\Model;

class User extends Model 
{
    public function profile()
    {
        return $this->hasOne('Profile','uid')->bind([
        		'email',
                'truename'	=> 'nickname',
                'profile_id'  => 'id',
            ]);
    }
}
于是我就加上了bind方法,指定返回email字段:
public static function getMessageListByPage($pageno, $rows)
    {
        $ruleList = [];
        //with 关联预载入
        $ruleList = collection(self::with('user')
        ->order('updatetime desc')
        ->page($pageno.','.$rows)
        ->field('uid, lastmessage, readstatus, file, appid')
        ->select())->toArray();
        return $ruleList;
    }
    //关联方法的使用
    //has_one(或has_many):外键在子关联对象中
    //belongs_to:外键在父联对象中
    //当有大量的关联数据需要查询的时候,一般都会考虑选择关联预载入的方式
    //预载人方法定义
    public function user()
    {
        // setEagerlyType设置预载入查询方式为 0 为 JOIN 1为 IN
        return $this->belongsTo('User', 'uid', 'id', [], 'LEFT')
        ->bind('email')
        ->setEagerlyType(0);
    }
然后查询结果如下:
[
    {
        "uid":45,
        "readstatus":0,
        "lastmessage":"0",
        "file":0,
        "createtime":0,
        "updatetime":0,
        "appid":0,
        "email":"xxxxxxxx@qq.com",
        "user":{
            "id":45,
            "group_id":3,
            "email":"xxxxxxxx@qq.com",
            "password":"xxxxxxxxxxxxx",
            "xxx":"xxxx"
        }
    }
]
坑爹呢,email字段是有了,但是user表的所有字段还是被查询出来了,连密码都查出来了,用脚趾头想也知道这指定不符合我的初衷,于是乎继续看文档,但是文档对这块介绍不多,我注意到文档里一句话
 
绑定关联属性不影响原有关联属性的读取,绑定关联模型的属性支持读取器。
 
所以说其实bind方法不会影响关联属性,也就是查询后附加的user 模型对象
 
解决方法是:
 //with的时候使用闭包查询
 ->with([
     'account' => function ($query) {
         $query->withField('id,user_id,account,frozen');
     }, ])
于是乎我再次去修改查询方法,加入闭包指定返回email字段:
public static function getMessageListByPage($pageno, $rows)
    {
        $ruleList = [];
        //with 关联预载入
        $ruleList = collection(self::with(
        ['user' => function($query){
        	$query->withField(['email']);
        }])
        ->order('updatetime desc')
        ->page($pageno.','.$rows)
        ->field('uid, lastmessage, readstatus, file, appid')
        ->select())->toArray();
        return $ruleList;
    }
    //关联方法的使用
    //has_one(或has_many):外键在子关联对象中
    //belongs_to:外键在父联对象中
    //当有大量的关联数据需要查询的时候,一般都会考虑选择关联预载入的方式
    //预载人方法定义
    public function user()
    {
        // setEagerlyType设置预载入查询方式为 0 为 JOIN 1为 IN
        return $this->belongsTo('User', 'uid', 'id', [], 'LEFT')
        ->bind(['email' => 'email',])
        ->setEagerlyType(0);
    }

查询结果为:
[
    {
        "uid":45,
        "readstatus":0,
        "lastmessage":"0",
        "file":0,
        "createtime":0,
        "updatetime":0,
        "appid":0,
        "email":"xxxxxxxx@qq.com",
        "user":{
            "email":"xxxxxxxx@qq.com",
        }
    }
]

到这里已经可以了  但还是无法取消user

最后说下,为什么上面无法取消user 因为他使用的是belongsTo 如果使用has的话就可以取消user 字段了
Copyright @ 2013-2021 元素模板 www.ys720.com All Rights Reserved. 版权所有 元素模板 www.ys720.com