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'):
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' ] );
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的数据(参数为对象属性)
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的数据(参数为闭包)
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方法很重要,官方手册写得很简单,建议参照本教程,多练习几遍。