php

ThinkPHP中hasWhere的用法

2023-09-20


在ThinkPHP中的模型关联中我们经常会用到hasWhere()的方法和has()的方法,本文就将hasWhere()方法和has()方法的用法做一个总结:


用途:hasWhere()方法用于通过关联数据,反查主表数据,如用户和银行卡的关联中,我们可以通过银行卡的信息,反查到用户的信息。


参数:hasWhere()方法的第一个参数为关联方法名(不是关联模型名),第二个参数为可选参数,为关联条件,关联条件可以是数组形式,也可以是闭包函数,或者组装好的模型构造器。


为了演示方便,我们定义个User模型及一个Card模型,并设置一对多关联,代码如下:


class User extends Model

{

    use SoftDelete;

    public function card(){

        return $this->hasMany('card','user_id','id')->bind(['card_num']);

    }

}

相应的需要定义Card模型,可以是空模型,但必须定义。


一、数组形式

User::hasWhere('card',['card_num'=>123])->select() // 查询卡号为123的用户信息

User::has('card','>',2)->select(); // 查询有两个以上卡号的用户

二、闭包形式

在hasWhere()的查询条件比较简单时,可以使用数组形式,但是查询条件稍微复杂一些的时候就需要用到闭包形式,如:


User::hasWhere('card', ['card_num' ,'<>', 123])->select() // 查询表达式错误:'Card_num'

类似这样的查询条件,我们就需要使用闭包的形式了。


User::hasWhere('card',function ($query){

return $query->where('card_num','<>',123);

})->select();

实际SQL查询语句为:'card_num'ELECT `User`.* FROM `think_user` `User` JOIN `think_card` `Card` ON `User`.`id`=`Card`.`user_id` WHERE ( `Card`.`card_num` <> '123' )  GROUP BY `User`.`id` 


三、组装好的查询构造器形式

如果还有更复杂的查询条件,我们也可以使用提前组装好查询构造器的形式来进行查询,如下:


$where = Card::where('card_num','<>',123);

$user = User::hasWhere('card',$where)->select();

实际SQL查询语句为:SELECT `User`.* FROM `think_user` `User` JOIN `think_card` `Card` ON `User`.`id`=`Card`.`user_id` WHERE ( `Card`.`card_num` <> '123' ) GROUP BY `User`.`id`


示例二和示例三中,我们使用了同样的需求,但是ThinkPHP底层其实使用了不同的SQL查询,一般来说,用组装好的查询构造器的形式,性能略好一点,但不明显。


四、总结:

hasWhere()的用法中,需要注意的两个点,一是,查询条件为第二个参数,二是,可以使用组装好的查询构造器作为查询条件,这一点经常被很多开发者所忽略。