where方法的用法是ThinkPHP查询语言的精髓,也是ThinkPHP ORM的重要组成部分和亮点所在,可以完成包括普通查询、表达式查询、快捷查询、区间查询、组合查询在内的查询操作。where方法的参数支持的变量类型包括字符串、数组和闭包。
和
where方法相同用法的方法还包括whereOr、whereIn等一系列快捷查询方法。
表达式查询
表达式查询是官方推荐使用的查询方式
查询表达式的使用格式:
Db::table('think_user')->where('id','>',1)->where('name','thinkphp')->select();
更多的表达式查询语法,可以参考前面的查询表达式部分。
数组条件
数组方式有两种查询条件类型:关联数组和索引数组。
关联数组
主要用于等值AND条件,例如:
// 传入数组作为查询条件Db::table('think_user')->where(['name' => 'thinkphp','status'=> 1])->select();
最后生成的SQL语句是
SELECT * FROM think_user WHERE `name`='thinkphp' AND status = 1
索引数组
索引数组方式批量设置查询条件,使用方式如下:
// 传入数组作为查询条件Db::table('think_user')->where([['name','=','thinkphp'],['status','=',1]])->select();
最后生成的SQL语句是
SELECT * FROM think_user WHERE `name`='thinkphp' AND status = 1
如果需要事先组装数组查询条件,可以使用:
$map[] = ['name','like','think'];$map[] = ['status','=',1];
数组方式查询还有一些额外的复杂用法,我们会在后面的高级查询章节提及。
字符串条件
使用字符串条件直接查询和操作,例如:
Db::table('think_user')->whereRaw('type=1 AND status=1')->select();
最后生成的SQL语句是
SELECT * FROM think_user WHERE type=1 AND status=1
注意使用字符串查询条件和表达式查询的一个区别在于,不会对查询字段进行避免关键词冲突处理。
使用字符串条件的时候,如果需要传入变量,建议配合预处理机制,确保更加安全,例如:
Db::table('think_user')->whereRaw("id=:id and username=:name", ['id' => 1 , 'name' => 'thinkphp'])->select();
字符串条件查询
对于一些实在复杂的查询,也可以直接使用原生SQL语句进行查询,例如:
Db::table('think_user')->whereRaw('id > 0 AND name LIKE "thinkphp%"')->select();
为了安全起见,我们可以对字符串查询条件使用参数绑定,例如:
Db::table('think_user')->whereRaw('id > :id AND name LIKE :name ', ['id' => 0, 'name' => 'thinkphp%'])->select();
条件查询
查询构造器支持条件查询,例如:
Db::name('user')->when($condition, function ($query) {// 满足条件后执行$query->where('score', '>', 80)->limit(10);})->select();
并且支持不满足条件的分支查询
Db::name('user')->when($condition, function ($query) {// 满足条件后执行$query->where('score', '>', 80)->limit(10);}, function ($query) {// 不满足条件执行$query->where('score', '>', 60);});
时间查询
框架内置了常用的时间查询方法,并且可以自动识别时间字段的类型,所以无论采用什么类型的时间字段,都可以统一使用本章的时间查询用法。
使用whereTime方法
whereTime方法提供了日期和时间字段的快捷查询,示例如下:
// 大于某个时间Db::name('user')->whereTime('birthday', '>=', '1970-10-1')->select();// 小于某个时间Db::name('user')->whereTime('birthday', '<', '2000-10-1')->select();// 时间区间查询Db::name('user')->whereTime('birthday', 'between', ['1970-10-1', '2000-10-1'])->select();// 不在某个时间区间Db::name('user')->whereTime('birthday', 'not between', ['1970-10-1', '2000-10-1'])->select();
还可以使用下面的时间表达式进行时间查询
// 查询两个小时内的博客Db::name('blog')->whereTime('create_time','-2 hours')->select();
查询某个时间区间whereBetweenTime
针对时间的区间查询,系统还提供了whereBetweenTime/whereNotBetweenTime快捷方法。
// 查询2017年上半年注册的用户Db::name('user')->whereBetweenTime('create_time', '2017-01-01', '2017-06-30')->select();// 查询不是2017年上半年注册的用户Db::name('user')->whereNotBetweenTime('create_time', '2017-01-01', '2017-06-30')->select();
查询某年whereYear
查询今年注册的用户
Db::name('user')->whereYear('create_time')->select();
查询去年注册的用户
Db::name('user')->whereYear('create_time', 'last year')->select();
查询某一年的数据使用
// 查询2018年注册的用户Db::name('user')->whereYear('create_time', '2018')->select();
查询某月whereMonth
查询本月注册的用户
Db::name('user')->whereMonth('create_time')->select();
查询上月注册用户
Db::name('user')->whereMonth('create_time','last month')->select();
查询2018年6月注册的用户
Db::name('user')->whereMonth('create_time', '2018-06')->select();
查询某周whereWeek
查询本周数据
Db::name(‘user’)
->whereWeek(‘create_time’)
->select();
查询上周数据
Db::name(‘user’)
->whereWeek(‘create_time’, ‘last week’)
->select();
查询指定某天开始的一周数据
// 查询2019-1-1到2019-1-7的注册用户
Db::name(‘user’)
->whereWeek(‘create_time’, ‘2019-1-1’)
->select();
查询某天whereDay
查询当天注册的用户
Db::name('user')->whereDay('create_time')->select();
查询昨天注册的用户
Db::name('user')->whereDay('create_time', 'yesterday')->select();
查询某天的数据使用
// 查询2018年6月1日注册的用户Db::name('user')->whereDay('create_time', '2018-06-01')->select();
时间字段区间比较whereBetweenTimeField
可以支持对两个时间字段的区间比较
// 查询有效期内的活动Db::name('event')->whereBetweenTimeField('start_time', 'end_time')->select();
上面的查询相当于
// 查询有效期内的活动Db::name('event')->whereTime('start_time', '<=', time())->whereTime('end_time', '>=', time())->select();
自定义时间查询规则
你可以通过在数据库配置文件中设置time_query_rule添加自定义的时间查询规则,
'time_query_rule' => ['hour' => ['1 hour ago', 'now'],],
批量(字段)查询where(Array)、whereOr(Array)
可以进行多个条件的批量条件查询定义,例如:
Db::table('think_user')->where([['name', 'like', 'thinkphp%'],['title', 'like', '%thinkphp'],['id', '>', 0],['status', '=', 1],])->select();
生成的SQL语句为:
SELECT * FROM `think_user` WHERE `name` LIKE 'thinkphp%' AND `title` LIKE '%thinkphp' AND `id` > 0 AND `status` = '1'
数组方式如果使用exp查询的话,一定要用raw方法。
Db::table('think_user')->where([['name', 'like', 'thinkphp%'],['title', 'like', '%thinkphp'],['id', 'exp', Db::raw('>score')],['status', '=', 1],])->select();
数组查询方式,确保你的查询数组不能被用户提交数据控制,用户提交的表单数据应该是作为查询数组的一个元素传入,如下:
Db::table('think_user')->where([['name', 'like', $name . '%'],['title', 'like', '%' . $title],['id', '>', $id],['status', '=', $status],])->select();
注意,相同的字段的多次查询条件可能会合并,如果希望某一个where方法里面的条件单独处理,可以使用下面的方式,避免被其它条件影响。
$map = [['name', 'like', 'thinkphp%'],['title', 'like', '%thinkphp'],['id', '>', 0],];Db::table('think_user')->where([ $map ])->where('status',1)->select();
生成的SQL语句为:
SELECT * FROM `think_user` WHERE ( `name` LIKE 'thinkphp%' AND `title` LIKE '%thinkphp' AND `id` > 0 ) AND `status` = '1'
如果使用下面的多个条件组合
$map1 = [['name', 'like', 'thinkphp%'],['title', 'like', '%thinkphp'],];$map2 = [['name', 'like', 'kancloud%'],['title', 'like', '%kancloud'],];Db::table('think_user')->whereOr([ $map1, $map2 ])->select();
生成的SQL语句为:
SELECT * FROM `think_user` WHERE ( `name` LIKE 'thinkphp%' AND `title` LIKE '%thinkphp' ) OR ( `name` LIKE 'kancloud%' AND `title` LIKE '%kancloud' )
善用多维数组查询,可以很方便的拼装出各种复杂的SQL语句
闭包查询
$name = 'thinkphp';$id = 10;Db::table('think_user')->where(function ($query) use($name, $id) {$query->where('name', $name)->whereOr('id', '>', $id);})->select();
生成的SQL语句为:
SELECT * FROM `think_user` WHERE ( `name` = 'thinkphp' OR `id` > 10 )
可见每个闭包条件两边也会自动加上括号。
混合查询
可以结合前面提到的所有方式进行混合查询,例如:
Db::table('think_user')->where('name', 'like', 'thinkphp%')->where(function ($query) {$query->where('id', '<', 10);})->select();
生成的SQL语句是:
SELECT * FROM `think_user` WHERE `name` LIKE 'thinkphp%' AND ( `id` < 10 )
快捷查询
快捷查询方式是一种多字段相同查询条件的简化写法,可以进一步简化查询条件的写法,在多个字段之间用|分割表示OR查询,用&分割表示AND查询,可以实现下面的查询,例如:
Db::table('think_user')->where('name|title','like','thinkphp%')->where('create_time&update_time','>',0)->find();
生成的查询SQL是:
SELECT * FROM `think_user` WHERE ( `name` LIKE 'thinkphp%' OR `title` LIKE 'thinkphp%' ) AND ( `create_time` > 0 AND `update_time` > 0 ) LIMIT 1
快捷查询支持所有的查询表达式。
快捷方法
系统封装了一系列快捷方法,用于简化查询,包括:
| 方法 | 作用 | | —- | —- |
|
whereOr
| 字段OR查询
|
|
whereXor
| 字段XOR查询
|
|
whereNull
| 查询字段是否为Null
|
|
whereNotNull
| 查询字段是否不为Null
|
|
whereIn
| 字段IN查询
|
|
whereNotIn
| 字段NOT IN查询
|
|
whereBetween
| 字段BETWEEN查询
|
|
whereNotBetween
| 字段NOT BETWEEN查询
|
|
whereLike
| 字段LIKE查询
|
|
whereNotLike
| 字段NOT LIKE查询
|
|
whereExists
| EXISTS条件查询
|
|
whereNotExists
| NOT EXISTS条件查询
|
|
whereExp
| 表达式查询
|
|
whereColumn
| 比较两个字段
|
whereOr的用法和where的用法相同,之不是条件是or
示例
whereLike示例
whereLike('name', 'xcwl%');
whereBetween示例
whereBetween('id', [10,20]);
whereIn示例
whereIn('id', [10,20]);
whereColumn示例
下面举例说明下两个字段比较的查询条件whereColumn方法的用法。
查询update_time大于create_time的用户数据
Db::table('think_user')->whereColumn('update_time','>','create_time')->select();
生成的SQL语句是:
SELECT * FROM `think_user` WHERE ( `update_time` > `create_time` )
查询name和nickname相同的用户数据
Db::table('think_user')->whereColumn('name','=','nickname')->select();
生成的SQL语句是:
SELECT * FROM `think_user` WHERE ( `name` = `nickname` )
相同字段条件也可以简化为
Db::table('think_user')->whereColumn('name','nickname')->select();
支持数组方式比较多个字段
Db::name('user')->whereColumn([['title', '=', 'name'],['update_time', '>=', 'create_time'],])->select();
生成的SQL语句是:
SELECT * FROM `think_user` WHERE ( `name` = `nickname` AND `update_time` > `create_time` )
动态查询
查询构造器还提供了动态查询机制,用于简化查询条件,包括:
| 动态查询 | 描述 | | —- | —- |
| whereFieldName | 查询某个字段的值 |
| whereOrFieldName | 查询某个字段的值 |
| getByFieldName | 根据某个字段查询 |
| getFieldByFieldName | 根据某个字段获取某个值 |
其中FieldName表示数据表的实际字段名称的驼峰法表示,假设数据表user中有email和nick_name字段,我们可以这样来查询。
// 根据邮箱(email)查询用户信息$user = Db::table('user')->whereEmail('thinkphp@qq.com')->find();// 根据昵称(nick_name)查询用户$email = Db::table('user')->whereNickName('like', '%流年%')->select();// 根据邮箱查询用户信息$user = Db::table('user')->getByEmail('thinkphp@qq.com');// 根据昵称(nick_name)查询用户信息$user = Db::table('user')->field('id,name,nick_name,email')->getByNickName('流年');// 根据邮箱查询用户的昵称$nickname = Db::table('user')->getFieldByEmail('thinkphp@qq.com', 'nick_name');// 根据昵称(nick_name)查询用户邮箱$email = Db::table('user')->getFieldByNickName('流年', 'email');
getBy和getFieldBy方法只会查询一条记录,可以和其它的链式方法搭配使用
