[TOC] ## select方法的使用 #### 1、 功能:根据查询器条件,生在查询SQL语句 #### 2、源码位置:/thinkphp/library/think/db/Builder.php >[success] 1、其实在Query.php查询类中也有一个select方法,使用是产生子查询; 2、该方法要产生查询结果,本质还是调用SQL生成器类Builder.php中select方法; 3、该类不是我们教学内容,等用到时再详细说明,本处不做过多介绍。 ~~~ /** * 生成查询SQL * @access public * @param array $options 表达式 * @return string */ public function select($options = []) { $sql = str_replace( ['%TABLE%', '%DISTINCT%', '%FIELD%', '%JOIN%', '%WHERE%', '%GROUP%', '%HAVING%', '%ORDER%', '%LIMIT%', '%UNION%', '%LOCK%', '', '%FORCE%'], [ $this->parseTable($options['table'], $options), $this->parseDistinct($options['distinct']), $this->parseField($options['field'], $options), $this->parseJoin($options['join'], $options), $this->parseWhere($options['where'], $options), $this->parseGroup($options['group']), $this->parseHaving($options['having']), $this->parseOrder($options['order'], $options), $this->parseLimit($options['limit']), $this->parseUnion($options['union']), $this->parseLock($options['lock']), $this->parseComment($options['comment']), $this->parseForce($options['force']), ], $this->selectSql); return $sql; } ~~~ * 源码分析: >[info] * 参数为数组,可以为空,即可不传入任何参数; * 返回是一个由各个条件组合而成的,完整的SELECT查询语句字符串; * 内部是通过一个str_replace()字符串替换函数实现,该函数有二个参数,均是数组形式; * 从字符替换函数第二个参数可以看出该select方法支持的连贯方法有哪些? * 方法有下面这些: `tabble,distinct,field,join,where,group,having,order,limit,union,lock,comment,force`等,这些方法,后面我们都将一一讲到。 * 在源码中,没有列出的连贯方法,就是不支持的方法,在select方法之前不要使用; * 这些方法,全部会拼接成查询选项,最终放在Query类的静态options属性数组中。 * Query 类中,有并查询要用的属性如下: ~~~ class Query { // 数据库Connection对象实例 protected $connection; // 数据库驱动类型 protected $builder; // 当前模型类名称 protected $model; // 当前数据表名称(含前缀) protected $table = ''; // 当前数据表名称(不含前缀) protected $name = ''; // 当前数据表主键 protected $pk; // 当前数据表前缀 protected $prefix = ''; // 查询参数 protected $options = []; // 参数绑定 protected $bind = []; // 数据表信息 protected static $info = []; ~~~ * 是不是很眼熟呢?对,我们之前学习过table和name方法,就是完成给静态属性$table和$name赋值的。 #### 3、参数和返回值 * 还记得SELECT语句最简单的形式吗?我们从此入手: * <font color="forestgreen">SELECT 字段列表 FROM 表名 WHERE 查询条件</font> * 字段列表由:field方法提供; * 数据表由:table方法、name方法或者db助手函数提供; * select 可接受Query类中$options查询参数属性做为参数; * 更多情况,查询条件由select之前的查询器方法提供; * select方法的参数推荐不填写,全部由前面查询器提供。 * select方法返回一个结果集,以二维数据表示; #### 4、适用环境或条件 >[success] * select方法是我们操作数据库时最重要的一方法 > * 该方法不是连贯操作(链式方法),在3.2.3中叫终级方法; > * 该方法定义在SQL生成器类中,一定要注意与普通连贯方法的区别; > * 该方法最典型的用法,就是放在所有连贯操作最后,用来生成SQL语句。 #### 5、调用语法: * 静态调用:用Db类静态方法实现 ~~~ Db::table(完整表名)->field(字段列表)->select(查询条件); //如定义了表前缀,可用name方法 Db::name(去前缀表名)->field(字段列表)->select(查询条件); ~~~ * 动态调用:用助手函数db实现 ~~~ db(去前缀表名)field(字段列表)->select(查询条件); ~~~ * 参数部分,如表名、字段列表、查询条件可以使用以下类型: | 序号 | 参数类型 | 说明 | | --- | --- | --- | | 1 | 字符串 | 这是最常用的,简单,直观 | | 2 | 数组 | 推荐使用,严谨规范,扩展性强 | | 3 | 布尔 | false:不执行查询,仅返回SQL语句,无true值| | 3 | 闭包 | 即匿名函数,可支持更多的查询方法 | #### 6、实例:查询id=1006的员工姓名和工资 > <font color="DeepPink">特别提示:</font> select参数仅限主键查询 目前表中数据如下: ![](https://box.kancloud.cn/d7c5b8f8b5633d449b16611dc10e435e_612x280.png) #### 1.字符串做select参数 ~~~ <?php namespace app\index\controller; use think\Db; class Index { public function index(){ //查询条件为字符串: dump(Db::table('tp5_staff')->field('id,name,salary')->select('1006')); } } ~~~ 查询结果如下: ~~~ array(1) { [0] => array(3) { ["id"] => int(1006) ["name"] => string(9) "西门庆" ["salary"] => float(19801) } } ~~~ >[info] 如果根据主键同时查询多条记录,可将多个主键写在一个字符串。 下面我们将代码中查询语句修改一下: ~~~ //查询条件为多个主键组成的字符串: dump(Db::table('tp5_staff')->field('id,name,salary')->select('1006,1008,1010')); ~~~ >[success]这时,应该返回主键id为1006、1008和1010三条记录 ~~~ array(3) { [0] => array(3) { ["id"] => int(1006) ["name"] => string(9) "西门庆" ["salary"] => float(19801) } [1] => array(3) { ["id"] => int(1008) ["name"] => string(6) "宋江" ["salary"] => float(9261) } [2] => array(3) { ["id"] => int(1010) ["name"] => string(9) "欧阳峰" ["salary"] => float(4900) } } ~~~ #### 2. 数组做select参数 ~~~ <?php namespace app\index\controller; use think\Db; class Index { public function index(){ //查询条件为字符串: dump(Db::table('tp5_staff')->field('id,name,salary')->select(['1006'])); } } ~~~ >[success] 可以看出,与字符串做参数相比,区别仅仅是把主键字符串做为元素,放在了索引数组中 查询结果如下: ~~~ array(1) { [0] => array(3) { ["id"] => int(1006) ["name"] => string(9) "西门庆" ["salary"] => float(19801) } } ~~~ >[success] 同字符串做参数类似,多个主键查询时,只需要把多个主键值做为数组元素即可 我们改写一下上面代码中关键语句: ~~~ //查询条件为多个主键字符串组成的索引数组: dump(Db::table('tp5_staff')->field('id,name,salary')->select(['1006','1008','1010'])); ~~~ >[success] 返回的查询结果与上面是一样的: ~~~ array(3) { [0] => array(3) { ["id"] => int(1006) ["name"] => string(9) "西门庆" ["salary"] => float(19801) } [1] => array(3) { ["id"] => int(1008) ["name"] => string(6) "宋江" ["salary"] => float(9261) } [2] => array(3) { ["id"] => int(1010) ["name"] => string(9) "欧阳峰" ["salary"] => float(4900) } } ~~~ >[success] 采用数组做为参数,可以构造更为复杂的查询条件,下面我们演示一下,在select方法中,用关联数组,构造更为复杂些查询表达式。 * 我们做关联数组方式,将上面的例子再次改写一下 ~~~ <?php namespace app\index\controller; use think\Db; class Index { public function index(){ //查询条件关联数组,键名为表主键,后面紧跟着给出条件: dump(Db::table('tp5_staff')->field('id,name,salary')->select(['id'=>['=','1010']])); } } ~~~ >[info] 有的同学,看到这里,可能有点发懵,这不是多此一举吗?明明一个字符串就可以解决的事,干吗整得这么复杂?那么问题来了: 1、如果要查询id大于1010的员工信息,怎么办? 2、如果要查询id号位于1010到1015之间的员工信息怎么办? 显然,字符串仅提供了简单的相等查询,更为复杂的查询,就无能为力了。 * 实例:查询id大于1010的员工信息 >明白上以上内容,现在就简单多了,只需要把比较运算符由“=”,换成“>”就行了 ~~~ <?php namespace app\index\controller; use think\Db; class Index { public function index(){ //查询条件关联数组,键名为表主键,后面紧跟着给出条件: dump(Db::table('tp5_staff')->field('id,name,salary')->select(['id'=>['>','1010']])); } } ~~~ * 查询结果如下: ~~~ array(2) { [0] => array(3) { ["id"] => int(1011) ["name"] => string(9) "李云龙" ["salary"] => float(4800) } [1] => array(3) { ["id"] => int(1012) ["name"] => string(9) "楚云飞" ["salary"] => float(4800) } } ~~~ #### 3、布尔值做select参数 >[warning] 1.只能填false,不能填:true 2.false:不执行查询,返回查询SQL语句 * Index.php : ~~~ <?php namespace app\index\controller; use think\Db; class Index { public function index(){ // 1.获取工资大于5000的员工信息 $result = Db::table('tp5_staff') //指定tp5_staff表 ->field(['id'=>'编号','name'=>'姓名','salary'=>'工资']) //设置返回字段 ->where('salary','>',5000) //设置查询条件 ->select(false); // 生成SQL语句字符串 // 2、输出查询SQL字符串 echo $result; } } ~~~ * 运行结果: ~~~ SELECT `id` AS `编号`,`name` AS `姓名`,`salary` AS `工资` FROM `tp5_staff` WHERE `salary` > 5000 ~~~ #### 4. 闭包做select参数 >[info] 1、补充知识:闭包就是匿名函数,所谓匿名,就是没有名字。 2、我们知道,变量或函数,都是按名调用,没有名称,如何调用呢? 3、匿名并不是没有名字,而是指名字不固定,是一个可随意变化的值; 4、匿名函数,一句话概括:就是用变量名来调用的函数。 * 实例:查询工资大于5000无的员工基本信息 ~~~ <?php namespace app\index\controller; use think\Db; class Index { public function index(){ //闭包参数支持更多的查询方法,可以构造更加复杂的查询器 dump(Db::select(function ($query){ $query->table('tp5_staff')->field('id,name,salary')->where('salary >= 5000'); })); } } ~~~ * 代码中的闭包函数部分,将select方法之前的所有查询器方法全部集成到了闭包中: ~~~ $query->table('tp5_staff')->field('id,name,salary')->where('salary >= 5000'); ~~~ * ThinkPHP 5 中大量的应用到了闭包查询,从现在起,同学们一定要适应这种变化 * * * * * ### 总结: >[success]1、select方法,除闭包外,不推荐使用参数; 2、所有查询条件,应该在前面用链式操作构成~~</font>