模型关联可以使用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', ]); } }
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'); }, ])
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 字段了