牛骨文教育服务平台(让学习变的简单)
博文笔记

tp5源码分析之数据库查询

创建时间:2018-02-23 投稿人: 浏览次数:175

1 查询对象

查询对象(Query)实现基本的查询操作

与模型不同的是,查询对象是在数据库的整体上进行操作,所以需要指定数据库表
模型针对的数据库中的某个数据表的操作。

2 查询操作

2-1 增删改查

$query->insert()

public function insert(array $data, $replace = false, $getLastInsID = false, $sequence = null)
    {
        // 分析查询表达式
        $options = $this->parseExpress();
        // 生成SQL语句
        $sql = $this->builder()->insert($data, $options, $replace);
        // 获取参数绑定
        $bind = $this->getBind();
        if ($options["fetch_sql"]) {
            // 获取实际执行的SQL语句
            return $this->connection->getRealSql($sql, $bind);
        }

        // 执行操作
        $result = $this->execute($sql, $bind);
        if ($getLastInsID) {
            $sequence = $sequence ?: (isset($options["sequence"]) ? $options["sequence"] : null);
            return $this->getLastInsID($sequence);
        }
        return $result;
    }

$query->insertAll()

public function insertAll(array $dataSet)
    {
        // 分析查询表达式
        $options = $this->parseExpress();
        if (!is_array(reset($dataSet))) {
            return false;
        }
        // 生成SQL语句
        $sql = $this->builder()->insertAll($dataSet, $options);
        // 获取参数绑定
        $bind = $this->getBind();
        if ($options["fetch_sql"]) {
            // 获取实际执行的SQL语句
            return $this->connection->getRealSql($sql, $bind);
        } else {
            // 执行操作
            return $this->execute($sql, $bind);
        }
    }

$query->selectInsert()

public function selectInsert($fields, $table)
    {
        // 分析查询表达式
        $options = $this->parseExpress();
        // 生成SQL语句
        $table = $this->parseSqlTable($table);
        $sql   = $this->builder()->selectInsert($fields, $table, $options);
        // 获取参数绑定
        $bind = $this->getBind();
        if ($options["fetch_sql"]) {
            // 获取实际执行的SQL语句
            return $this->connection->getRealSql($sql, $bind);
        } else {
            // 执行操作
            return $this->execute($sql, $bind);
        }
    }

$query->select()

public function select($data = null)
    {
        if ($data instanceof Query) {
            return $data->select();
        } elseif ($data instanceof Closure) {
            call_user_func_array($data, [ & $this]);
            $data = null;
        }
        // 分析查询表达式
        $options = $this->parseExpress();

        if (false === $data) {
            // 用于子查询 不查询只返回SQL
            $options["fetch_sql"] = true;
        } elseif (!is_null($data)) {
            // 主键条件分析
            $this->parsePkWhere($data, $options);
        }

        $resultSet = false;
        if (empty($options["fetch_sql"]) && !empty($options["cache"])) {
            // 判断查询缓存
            $cache = $options["cache"];
            unset($options["cache"]);
            $key       = is_string($cache["key"]) ? $cache["key"] : md5(serialize($options));
            $resultSet = Cache::get($key);
        }
        if (!$resultSet) {
            // 生成查询SQL
            $sql = $this->builder()->select($options);
            // 获取参数绑定
            $bind = $this->getBind();
            if ($options["fetch_sql"]) {
                // 获取实际执行的SQL语句
                return $this->connection->getRealSql($sql, $bind);
            }
            // 执行查询操作
            $resultSet = $this->query($sql, $bind, $options["master"], $options["fetch_class"]);

            if ($resultSet instanceof PDOStatement) {
                // 返回PDOStatement对象
                return $resultSet;
            }

            if (isset($cache)) {
                // 缓存数据集
                if (isset($cache["tag"])) {
                    Cache::tag($cache["tag"])->set($key, $resultSet, $cache["expire"]);
                } else {
                    Cache::set($key, $resultSet, $cache["expire"]);
                }
            }
        }

        // 返回结果处理
        if (count($resultSet) > 0) {
            // 数据列表读取后的处理
            if (!empty($this->model)) {
                // 生成模型对象
                $model = $this->model;
                foreach ($resultSet as $key => $result) {
                    /** @var Model $result */
                    $result = new $model($result);
                    $result->isUpdate(true);
                    // 关联查询
                    if (!empty($options["relation"])) {
                        $result->relationQuery($options["relation"]);
                    }
                    $resultSet[$key] = $result;
                }
                if (!empty($options["with"]) && $result instanceof Model) {
                    // 预载入
                    $resultSet = $result->eagerlyResultSet($resultSet, $options["with"], is_object($resultSet) ? get_class($resultSet) : "");
                }
            }
        } elseif (!empty($options["fail"])) {
            $this->throwNotFound($options);
        }
        return $resultSet;
    }

$query->find()

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:" . $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 ($this->allowField) {
                    $data->allowField($this->allowField);
                }
                // 关联查询
                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;
    }

$query->update()

public function update(array $data)
    {
        $options = $this->parseExpress();
        $pk      = $this->getPk($options);
        if (isset($options["cache"]) && is_string($options["cache"])) {
            $key = $options["cache"];
        }

        if (empty($options["where"])) {
            // 如果存在主键数据 则自动作为更新条件
            if (is_string($pk) && isset($data[$pk])) {
                $where[$pk] = $data[$pk];
                if (!isset($key)) {
                    $key = "think:" . $options["table"] . "|" . $data[$pk];
                }
                unset($data[$pk]);
            } elseif (is_array($pk)) {
                // 增加复合主键支持
                foreach ($pk as $field) {
                    if (isset($data[$field])) {
                        $where[$field] = $data[$field];
                    } else {
                        // 如果缺少复合主键数据则不执行
                        throw new Exception("miss complex primary data");
                    }
                    unset($data[$field]);
                }
            }
            if (!isset($where)) {
                // 如果没有任何更新条件则不执行
                throw new Exception("miss update condition");
            } else {
                $options["where"]["AND"] = $where;
            }
        } elseif (is_string($pk) && isset($options["where"]["AND"][$pk]) && is_scalar($options["where"]["AND"][$pk])) {
            $key = "think:" . $options["table"] . "|" . $options["where"]["AND"][$pk];
        }
        // 生成UPDATE SQL语句
        $sql = $this->builder()->update($data, $options);
        // 获取参数绑定
        $bind = $this->getBind();
        if ($options["fetch_sql"]) {
            // 获取实际执行的SQL语句
            return $this->connection->getRealSql($sql, $bind);
        } else {
            // 检测缓存
            if (isset($key) && Cache::get($key)) {
                // 删除缓存
                Cache::rm($key);
            }
            // 执行操作
            return "" == $sql ? 0 : $this->execute($sql, $bind);
        }
    }

$query->delete()

public function delete($data = null)
    {
        // 分析查询表达式
        $options = $this->parseExpress();
        if (isset($options["cache"]) && is_string($options["cache"])) {
            $key = $options["cache"];
        }

        if (!is_null($data) && true !== $data) {
            if (!isset($key) && !is_array($data)) {
                // 缓存标识
                $key = "think:" . $options["table"] . "|" . $data;
            }
            // AR模式分析主键条件
            $this->parsePkWhere($data, $options);
        }

        if (true !== $data && empty($options["where"])) {
            // 如果条件为空 不进行删除操作 除非设置 1=1
            throw new Exception("delete without condition");
        }
        // 生成删除SQL语句
        $sql = $this->builder()->delete($options);
        // 获取参数绑定
        $bind = $this->getBind();
        if ($options["fetch_sql"]) {
            // 获取实际执行的SQL语句
            return $this->connection->getRealSql($sql, $bind);
        }

        // 检测缓存
        if (isset($key) && Cache::get($key)) {
            // 删除缓存
            Cache::rm($key);
        }
        // 执行操作
        return $this->execute($sql, $bind);
    }

2-2 事务操作

$query->startTrans()

启动事务

public function startTrans()
    {
        $this->connection->startTrans();
    }

$query->commit()

提交事务

public function commit()
    {
        $this->connection->commit();
    }

$query->transaction()

执行事务

public function transaction($callback)
   {
       return $this->connection->transaction($callback);
   }

$query->rollback()

回滚事务

public function rollback()
    {
        $this->connection->rollback();
    }

2-3 sql语句操作

$query->query()

调用连接器的静态query方法

public function query($sql, $bind = [], $master = false, $class = false)
    {
        return $this->connection->query($sql, $bind, $master, $class);
    }

$query->execute()

调用连接器的静态query方法

            
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。