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、实例:

  • 现在表中的数据如下图:
  1. 选择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'));
 } 
}
  1. 选择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']));
 } 
}
  1. 选择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));
 } 
}
  1. 选择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方法很重要,官方手册写得很简单,建议参照本教程,多练习几遍。