where方法的用法是ThinkPHP查询语言的精髓,也是ThinkPHP ORM的重要组成部分和亮点所在,可以完成包括普通查询、表达式查询、快捷查询、区间查询、组合查询在内的查询操作。where方法的参数支持的变量类型包括字符串、数组和闭包。

where方法相同用法的方法还包括whereOrwhereIn等一系列快捷查询方法。

表达式查询

表达式查询是官方推荐使用的查询方式
查询表达式的使用格式:

  1. Db::table('think_user')
  2. ->where('id','>',1)
  3. ->where('name','thinkphp')
  4. ->select();

更多的表达式查询语法,可以参考前面的查询表达式部分。

数组条件

数组方式有两种查询条件类型:关联数组和索引数组。

关联数组

主要用于等值AND条件,例如:

  1. // 传入数组作为查询条件
  2. Db::table('think_user')->where([
  3. 'name' => 'thinkphp',
  4. 'status'=> 1
  5. ])->select();

最后生成的SQL语句是

  1. SELECT * FROM think_user WHERE `name`='thinkphp' AND status = 1

索引数组

索引数组方式批量设置查询条件,使用方式如下:

  1. // 传入数组作为查询条件
  2. Db::table('think_user')->where([
  3. ['name','=','thinkphp'],
  4. ['status','=',1]
  5. ])->select();

最后生成的SQL语句是

  1. SELECT * FROM think_user WHERE `name`='thinkphp' AND status = 1

如果需要事先组装数组查询条件,可以使用:

  1. $map[] = ['name','like','think'];
  2. $map[] = ['status','=',1];

数组方式查询还有一些额外的复杂用法,我们会在后面的高级查询章节提及。

字符串条件

使用字符串条件直接查询和操作,例如:

  1. Db::table('think_user')->whereRaw('type=1 AND status=1')->select();

最后生成的SQL语句是

  1. SELECT * FROM think_user WHERE type=1 AND status=1

注意使用字符串查询条件和表达式查询的一个区别在于,不会对查询字段进行避免关键词冲突处理。

使用字符串条件的时候,如果需要传入变量,建议配合预处理机制,确保更加安全,例如:

  1. Db::table('think_user')
  2. ->whereRaw("id=:id and username=:name", ['id' => 1 , 'name' => 'thinkphp'])
  3. ->select();

字符串条件查询

对于一些实在复杂的查询,也可以直接使用原生SQL语句进行查询,例如:

  1. Db::table('think_user')
  2. ->whereRaw('id > 0 AND name LIKE "thinkphp%"')
  3. ->select();

为了安全起见,我们可以对字符串查询条件使用参数绑定,例如:

  1. Db::table('think_user')
  2. ->whereRaw('id > :id AND name LIKE :name ', ['id' => 0, 'name' => 'thinkphp%'])
  3. ->select();

条件查询

查询构造器支持条件查询,例如:

  1. Db::name('user')->when($condition, function ($query) {
  2. // 满足条件后执行
  3. $query->where('score', '>', 80)->limit(10);
  4. })->select();

并且支持不满足条件的分支查询

  1. Db::name('user')->when($condition, function ($query) {
  2. // 满足条件后执行
  3. $query->where('score', '>', 80)->limit(10);
  4. }, function ($query) {
  5. // 不满足条件执行
  6. $query->where('score', '>', 60);
  7. });

时间查询

框架内置了常用的时间查询方法,并且可以自动识别时间字段的类型,所以无论采用什么类型的时间字段,都可以统一使用本章的时间查询用法。

使用whereTime方法

whereTime方法提供了日期和时间字段的快捷查询,示例如下:

  1. // 大于某个时间
  2. Db::name('user')
  3. ->whereTime('birthday', '>=', '1970-10-1')
  4. ->select();
  5. // 小于某个时间
  6. Db::name('user')
  7. ->whereTime('birthday', '<', '2000-10-1')
  8. ->select();
  9. // 时间区间查询
  10. Db::name('user')
  11. ->whereTime('birthday', 'between', ['1970-10-1', '2000-10-1'])
  12. ->select();
  13. // 不在某个时间区间
  14. Db::name('user')
  15. ->whereTime('birthday', 'not between', ['1970-10-1', '2000-10-1'])
  16. ->select();

还可以使用下面的时间表达式进行时间查询

  1. // 查询两个小时内的博客
  2. Db::name('blog')
  3. ->whereTime('create_time','-2 hours')
  4. ->select();

查询某个时间区间whereBetweenTime

针对时间的区间查询,系统还提供了whereBetweenTime/whereNotBetweenTime快捷方法。

  1. // 查询2017年上半年注册的用户
  2. Db::name('user')
  3. ->whereBetweenTime('create_time', '2017-01-01', '2017-06-30')
  4. ->select();
  5. // 查询不是2017年上半年注册的用户
  6. Db::name('user')
  7. ->whereNotBetweenTime('create_time', '2017-01-01', '2017-06-30')
  8. ->select();

查询某年whereYear

查询今年注册的用户

  1. Db::name('user')
  2. ->whereYear('create_time')
  3. ->select();

查询去年注册的用户

  1. Db::name('user')
  2. ->whereYear('create_time', 'last year')
  3. ->select();

查询某一年的数据使用

  1. // 查询2018年注册的用户
  2. Db::name('user')
  3. ->whereYear('create_time', '2018')
  4. ->select();

查询某月whereMonth

查询本月注册的用户

  1. Db::name('user')
  2. ->whereMonth('create_time')
  3. ->select();

查询上月注册用户

  1. Db::name('user')
  2. ->whereMonth('create_time','last month')
  3. ->select();

查询2018年6月注册的用户

  1. Db::name('user')
  2. ->whereMonth('create_time', '2018-06')
  3. ->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

查询当天注册的用户

  1. Db::name('user')
  2. ->whereDay('create_time')
  3. ->select();

查询昨天注册的用户

  1. Db::name('user')
  2. ->whereDay('create_time', 'yesterday')
  3. ->select();

查询某天的数据使用

  1. // 查询2018年6月1日注册的用户
  2. Db::name('user')
  3. ->whereDay('create_time', '2018-06-01')
  4. ->select();

时间字段区间比较whereBetweenTimeField

可以支持对两个时间字段的区间比较

  1. // 查询有效期内的活动
  2. Db::name('event')
  3. ->whereBetweenTimeField('start_time', 'end_time')
  4. ->select();

上面的查询相当于

  1. // 查询有效期内的活动
  2. Db::name('event')
  3. ->whereTime('start_time', '<=', time())
  4. ->whereTime('end_time', '>=', time())
  5. ->select();

自定义时间查询规则

你可以通过在数据库配置文件中设置time_query_rule添加自定义的时间查询规则,

  1. 'time_query_rule' => [
  2. 'hour' => ['1 hour ago', 'now'],
  3. ],

批量(字段)查询where(Array)whereOr(Array)

可以进行多个条件的批量条件查询定义,例如:

  1. Db::table('think_user')
  2. ->where([
  3. ['name', 'like', 'thinkphp%'],
  4. ['title', 'like', '%thinkphp'],
  5. ['id', '>', 0],
  6. ['status', '=', 1],
  7. ])
  8. ->select();

生成的SQL语句为:

  1. SELECT * FROM `think_user` WHERE `name` LIKE 'thinkphp%' AND `title` LIKE '%thinkphp' AND `id` > 0 AND `status` = '1'

数组方式如果使用exp查询的话,一定要用raw方法。

  1. Db::table('think_user')
  2. ->where([
  3. ['name', 'like', 'thinkphp%'],
  4. ['title', 'like', '%thinkphp'],
  5. ['id', 'exp', Db::raw('>score')],
  6. ['status', '=', 1],
  7. ])
  8. ->select();

数组查询方式,确保你的查询数组不能被用户提交数据控制,用户提交的表单数据应该是作为查询数组的一个元素传入,如下:

  1. Db::table('think_user')
  2. ->where([
  3. ['name', 'like', $name . '%'],
  4. ['title', 'like', '%' . $title],
  5. ['id', '>', $id],
  6. ['status', '=', $status],
  7. ])
  8. ->select();

注意,相同的字段的多次查询条件可能会合并,如果希望某一个where方法里面的条件单独处理,可以使用下面的方式,避免被其它条件影响。

  1. $map = [
  2. ['name', 'like', 'thinkphp%'],
  3. ['title', 'like', '%thinkphp'],
  4. ['id', '>', 0],
  5. ];
  6. Db::table('think_user')
  7. ->where([ $map ])
  8. ->where('status',1)
  9. ->select();

生成的SQL语句为:

  1. SELECT * FROM `think_user` WHERE ( `name` LIKE 'thinkphp%' AND `title` LIKE '%thinkphp' AND `id` > 0 ) AND `status` = '1'

如果使用下面的多个条件组合

  1. $map1 = [
  2. ['name', 'like', 'thinkphp%'],
  3. ['title', 'like', '%thinkphp'],
  4. ];
  5. $map2 = [
  6. ['name', 'like', 'kancloud%'],
  7. ['title', 'like', '%kancloud'],
  8. ];
  9. Db::table('think_user')
  10. ->whereOr([ $map1, $map2 ])
  11. ->select();

生成的SQL语句为:

  1. SELECT * FROM `think_user` WHERE ( `name` LIKE 'thinkphp%' AND `title` LIKE '%thinkphp' ) OR ( `name` LIKE 'kancloud%' AND `title` LIKE '%kancloud' )

善用多维数组查询,可以很方便的拼装出各种复杂的SQL语句

闭包查询

  1. $name = 'thinkphp';
  2. $id = 10;
  3. Db::table('think_user')->where(function ($query) use($name, $id) {
  4. $query->where('name', $name)
  5. ->whereOr('id', '>', $id);
  6. })->select();

生成的SQL语句为:

  1. SELECT * FROM `think_user` WHERE ( `name` = 'thinkphp' OR `id` > 10 )

可见每个闭包条件两边也会自动加上括号。

混合查询

可以结合前面提到的所有方式进行混合查询,例如:

  1. Db::table('think_user')
  2. ->where('name', 'like', 'thinkphp%')
  3. ->where(function ($query) {
  4. $query->where('id', '<', 10);
  5. })
  6. ->select();

生成的SQL语句是:

  1. SELECT * FROM `think_user` WHERE `name` LIKE 'thinkphp%' AND ( `id` < 10 )

快捷查询

快捷查询方式是一种多字段相同查询条件的简化写法,可以进一步简化查询条件的写法,在多个字段之间用|分割表示OR查询,用&分割表示AND查询,可以实现下面的查询,例如:

  1. Db::table('think_user')
  2. ->where('name|title','like','thinkphp%')
  3. ->where('create_time&update_time','>',0)
  4. ->find();

生成的查询SQL是:

  1. 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示例

  1. whereLike('name', 'xcwl%');

whereBetween示例

  1. whereBetween('id', [10,20]);

whereIn示例

  1. whereIn('id', [10,20]);

whereColumn示例

下面举例说明下两个字段比较的查询条件whereColumn方法的用法。
查询update_time大于create_time的用户数据

  1. Db::table('think_user')
  2. ->whereColumn('update_time','>','create_time')
  3. ->select();

生成的SQL语句是:

  1. SELECT * FROM `think_user` WHERE ( `update_time` > `create_time` )

查询namenickname相同的用户数据

  1. Db::table('think_user')
  2. ->whereColumn('name','=','nickname')
  3. ->select();

生成的SQL语句是:

  1. SELECT * FROM `think_user` WHERE ( `name` = `nickname` )

相同字段条件也可以简化为

  1. Db::table('think_user')
  2. ->whereColumn('name','nickname')
  3. ->select();

支持数组方式比较多个字段

  1. Db::name('user')->whereColumn([
  2. ['title', '=', 'name'],
  3. ['update_time', '>=', 'create_time'],
  4. ])->select();

生成的SQL语句是:

  1. SELECT * FROM `think_user` WHERE ( `name` = `nickname` AND `update_time` > `create_time` )

动态查询

查询构造器还提供了动态查询机制,用于简化查询条件,包括:

| 动态查询 | 描述 | | —- | —- |

| whereFieldName | 查询某个字段的值 |

| whereOrFieldName | 查询某个字段的值 |

| getByFieldName | 根据某个字段查询 |

| getFieldByFieldName | 根据某个字段获取某个值 |

其中FieldName表示数据表的实际字段名称的驼峰法表示,假设数据表user中有emailnick_name字段,我们可以这样来查询。

  1. // 根据邮箱(email)查询用户信息
  2. $user = Db::table('user')
  3. ->whereEmail('thinkphp@qq.com')
  4. ->find();
  5. // 根据昵称(nick_name)查询用户
  6. $email = Db::table('user')
  7. ->whereNickName('like', '%流年%')
  8. ->select();
  9. // 根据邮箱查询用户信息
  10. $user = Db::table('user')
  11. ->getByEmail('thinkphp@qq.com');
  12. // 根据昵称(nick_name)查询用户信息
  13. $user = Db::table('user')
  14. ->field('id,name,nick_name,email')
  15. ->getByNickName('流年');
  16. // 根据邮箱查询用户的昵称
  17. $nickname = Db::table('user')
  18. ->getFieldByEmail('thinkphp@qq.com', 'nick_name');
  19. // 根据昵称(nick_name)查询用户邮箱
  20. $email = Db::table('user')
  21. ->getFieldByNickName('流年', 'email');

getBygetFieldBy方法只会查询一条记录,可以和其它的链式方法搭配使用