ThinkPHP5 Model关联查询返回指定字段

ThinkPHP5 Model关联查询返回指定字段

如题,我在写一个接口时需要用到关联查询,因为对ThinkPHP5 不熟悉,去查询官方文档,使用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 模型对象
得嘞,去百度看看还有没有其他解决办法,果然找到一个 fastadmin 社区帖子
他给出的解决方法是:

 //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去除,但是觉得应该还有更优雅的方法,记录下来找到合适的方式再更新,

  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值