select方法

select方法的使用

1、 功能:根据查询器条件,生在查询SQL语句

2、源码位置:/thinkphp/library/think/db/Builder.php

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%', '%COMMENT%', '%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; }


  • 源码分析:


    • 参数为数组,可以为空,即可不传入任何参数;
    • 返回是一个由各个条件组合而成的,完整的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语句最简单的形式吗?我们从此入手:

    • SELECT 字段列表 FROM 表名 WHERE 查询条件
    • 字段列表由:field方法提供;
    • 数据表由:table方法、name方法或者db助手函数提供;
    • select 可接受Query类中$options查询参数属性做为参数;
    • 更多情况,查询条件由select之前的查询器方法提供;
    • select方法的参数推荐不填写,全部由前面查询器提供。
  • select方法返回一个结果集,以二维数据表示;

    4、适用环境或条件

    • 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的员工姓名和工资

特别提示:select参数仅限主键查询

目前表中数据如下:

1.字符串做select参数

field('id,name,salary')->select('1006')); } }

查询结果如下:

array(1) { [0] => array(3) { ["id"] => int(1006) ["name"] => string(9) "西门庆" ["salary"] => float(19801) } }

如果根据主键同时查询多条记录,可将多个主键写在一个字符串。
下面我们将代码中查询语句修改一下:

//查询条件为多个主键组成的字符串: dump(Db::table('tp5_staff')->field('id,name,salary')->select('1006,1008,1010'));

这时,应该返回主键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参数

field('id,name,salary')->select(['1006'])); } }

可以看出,与字符串做参数相比,区别仅仅是把主键字符串做为元素,放在了索引数组中

查询结果如下:

array(1) { [0] => array(3) { ["id"] => int(1006) ["name"] => string(9) "西门庆" ["salary"] => float(19801) } }

同字符串做参数类似,多个主键查询时,只需要把多个主键值做为数组元素即可
我们改写一下上面代码中关键语句:

//查询条件为多个主键字符串组成的索引数组: dump(Db::table('tp5_staff')->field('id,name,salary')->select(['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) } }

采用数组做为参数,可以构造更为复杂的查询条件,下面我们演示一下,在select方法中,用关联数组,构造更为复杂些查询表达式。

  • 我们做关联数组方式,将上面的例子再次改写一下
field('id,name,salary')->select(['id'=>['=','1010']])); } }

有的同学,看到这里,可能有点发懵,这不是多此一举吗?明明一个字符串就可以解决的事,干吗整得这么复杂?那么问题来了:
1、如果要查询id大于1010的员工信息,怎么办?
2、如果要查询id号位于1010到1015之间的员工信息怎么办?
显然,字符串仅提供了简单的相等查询,更为复杂的查询,就无能为力了。

  • 实例:查询id大于1010的员工信息

明白上以上内容,现在就简单多了,只需要把比较运算符由“=”,换成“>”就行了

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参数

1.只能填false,不能填:true
2.false:不执行查询,返回查询SQL语句

  • Index.php :
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参数

1、补充知识:闭包就是匿名函数,所谓匿名,就是没有名字。
2、我们知道,变量或函数,都是按名调用,没有名称,如何调用呢?
3、匿名并不是没有名字,而是指名字不固定,是一个可随意变化的值;
4、匿名函数,一句话概括:就是用变量名来调用的函数。

  • 实例:查询工资大于5000无的员工基本信息
table('tp5_staff')->field('id,name,salary')->where('salary >= 5000'); })); } }
  • 代码中的闭包函数部分,将select方法之前的所有查询器方法全部集成到了闭包中:
$query->table('tp5_staff')->field('id,name,salary')->where('salary >= 5000');
  • ThinkPHP 5 中大量的应用到了闭包查询,从现在起,同学们一定要适应这种变化

总结:

1、select方法,除闭包外,不推荐使用参数;
2、所有查询条件,应该在前面用链式操作构成~~