ThinkPHP5数据库实例详解
/ find方法
find方法
find方法的使用
1、功能:获取数据表中,满足条件的单条记录。
2、源码位置:/thinkphp/library/think/db/Query.php (1954行 ~ 2041行)
/**
* 查找单条记录
* @access public
* @param array|string|Query|\Closure $data
* @return array|false|\PDOStatement|string|Model
* @throws DbException
* @throws ModelNotFoundException
* @throws DataNotFoundException
*/
public function find($data = null)
{
if ($data instanceof Query) {
return $data->find();
} elseif ($data instanceof \Closure) {
call_user_func_array($data, [ & $this]);
$data = null;
}
// 分析查询表达式
$options = $this->parseExpress();
if (!is_null($data)) {
// AR模式分析主键条件
$this->parsePkWhere($data, $options);
}
$options['limit'] = 1;
$result = false;
if (empty($options['fetch_sql']) && !empty($options['cache'])) {
// 判断查询缓存
$cache = $options['cache'];
if (true === $cache['key'] && !is_null($data) && !is_array($data)) {
$key = 'think:' . (is_array($options['table']) ? key($options['table']) : $options['table']) . '|' . $data;
} else {
$key = is_string($cache['key']) ? $cache['key'] : md5(serialize($options));
}
$result = Cache::get($key);
}
if (!$result) {
// 生成查询SQL
$sql = $this->builder()->select($options);
// 获取参数绑定
$bind = $this->getBind();
if ($options['fetch_sql']) {
// 获取实际执行的SQL语句
return $this->connection->getRealSql($sql, $bind);
}
// 执行查询
$result = $this->query($sql, $bind, $options['master'], $options['fetch_class']);
if ($result instanceof \PDOStatement) {
// 返回PDOStatement对象
return $result;
}
if (isset($cache)) {
// 缓存数据
if (isset($cache['tag'])) {
Cache::tag($cache['tag'])->set($key, $result, $cache['expire']);
} else {
Cache::set($key, $result, $cache['expire']);
}
}
}
// 数据处理
if (!empty($result[0])) {
$data = $result[0];
if (!empty($this->model)) {
// 返回模型对象
$model = $this->model;
$data = new $model($data);
$data->isUpdate(true, isset($options['where']['AND']) ? $options['where']['AND'] : null);
// 关联查询
if (!empty($options['relation'])) {
$data->relationQuery($options['relation']);
}
if (!empty($options['with'])) {
// 预载入
$data->eagerlyResult($data, $options['with'], is_object($result) ? get_class($result) : '');
}
}
} elseif (!empty($options['fail'])) {
$this->throwNotFound($options);
} else {
$data = null;
}
return $data;
}
3、参数与返回值:
- 阅读源码发现:参数支持四种类型:
序号 | 参数类型 | 说明 |
---|---|---|
1 | 数组 | 首选 |
2 | 字符串 | 灵活、直观,但不够规范 |
3 | 对象 | 用的不多,后面有实例演示 |
4 | 闭包 | 即匿名函数,详情见后观实例 |
参数最终组成一条用在SQL语句中WHERE的条件表达式,;
-
返回值:
序号 参数类型 说明 1 一维关联数组 与数据表某条记录对应,键名对应字段名,键值对应字段值,最常用 2 布尔值 查询是否成功?true:成功,faluse:失败 3 PDO对象 不常用 4 模型 这在模型课程中,我们再详细讨论
4、适用环境:
- 根据主键查询,确定只返回一条记录;
- 如果返回多满足条件的记录,该方法仅返回第一条,一定要注意;
5、调用语法(以:tp5_staff表为例):
- 通过 Db.php类中的:static _callStatic() 自动实现静态方法调用(了解即可)
- Query对象调用:find(查询表达式)
序号 | 参数类型 | 说明 |
---|---|---|
1 | 主键 | find( '主键' ); |
2 | 数组 | find( [ '条件' => 表达式 ] ); |
3 | 闭包 | find( function ($query) { $query = 查询表达式 } ) |
6、实例:
- 现在表中的数据如下图:
- 选择tp5_staff表,查询id等于1006的数据(参数为主键)
- find('1006'):
<?php
namespace app\index\controller;
use think\Db;
class Index {
public function index(){
//使用Db类方法查询,并输出查询结果
dump(Db::table('tp5_staff')->find('1006'));
}
}
- 选择tp5_staff表,查询id等于1006的数据(参数为数组)
- 将代码中:
find( '1006' )
换成 :find( [ 'id' => '1006' ] );
<?php
namespace app\index\controller;
use think\Db;
class Index {
public function index(){
//使用Db类方法查询,并输出查询结果
dump(Db::table('tp5_staff')->find(['id'=>'1006']));
}
}
- 选择tp5_staff表,查询id等于1006的数据(参数为对象属性)
<?php
namespace app\index\controller;
use think\Db;
class Index {
public function index(){
//创建标准对象$query
$query = new \stdClass;
//$query对象创建属性id ,并赋值为主键
$query -> id = 1006;
//将$query->id做为条件赋给条件变量 $where
$where = $query -> id;
//根据对象属性设置的条件,查询数据
dump(Db::table('tp5_staff')->find($where));
}
}
- 选择tp5_staff表,查询id等于1006的数据(参数为闭包)
<?php
namespace app\index\controller;
use think\Db;
class Index {
public function index(){
//直接用Db类调用find(),将所有条件用闭包函数给出
dump(Db::find(function ($query){
$query = Db::table('tp5_staff')->where(['id'=>1006]);
}));
}
}
-
闭包函数:
- 也要匿名函数,顾名思议,该函数没有名称,不能按名调用;
- 匿名函数以变量为载体,用变量调用;
- 闭包函数非常适合创建非常复杂的查询条件,请一定要读懂学会;
- 如果仍觉得理解困难,请再复习一下PHP函数部分知识。
-
运行结果:
array(7) {
["id"] => int(1006)
["name"] => string(9) "西门庆"
["sex"] => int(0)
["age"] => int(22)
["salary"] => float(19801)
["dept"] => string(9) "市场部"
["hiredate"] => string(10) "2008-12-02"
}
7、局限性或注意事项:
- find方法仅返回第一条满足条件的记录,适合预先知道只会有一条或没有记录时使用;
- 闭包中的很多条件,可以用在find之前的链式操作中,但推荐全部放在闭包中;
- 日常开发中,我们更多的使用模型中的get方法获取单条记录。
小作业:
find方法很重要,官方手册写得很简单,建议参照本教程,多练习几遍。