## `PDO` 组件 PDO 组件用于 MySQL 等关系型数据库的操作,语法简单明了,且具有独特的查询构造方式,可构造任何复杂的SQL。 >[success] 该组件基于 pdo 扩展,[语句预处理](http://php.net/manual/zh/pdo.prepared-statements.php) 将帮助你免于SQL注入攻击。 | 类 | 调用 | 连接方式 | | --- | --- | --- | | mix\client\PDO | app()->pdo | 短连接 | | 门面类 (通常在 HTTP 开发中使用) | 调用 | | --- | --- | | mix\facades\PDO | PDO:: | | 通过配置实例化调用 (通常在命令行开发使用) | | --- | | $pdo = mix\client\PDO::newInstanceByConfig('libraries.[***]'); | ## 组件配置 App配置文件中,该组件的默认配置如下: [>> 到 GitHub 查看默认配置 <<](https://github.com/mixstart/mixphp/blob/master/apps/httpd/config/http_permanent.php#L169) ## 插入 ~~~ $data = [ 'name' => 'xiaoliu', 'content' => 'hahahaha', ]; $success = PDO::insert('post', $data)->execute(); // 获得刚插入数据的id $insertId = PDO::getLastInsertId(); ~~~ ## 批量插入 ~~~ $data = [ ['name' => 'xiaoliu', 'content' => 'hahahaha'], ['name' => 'xiaoliu', 'content' => 'hahahaha'], ['name' => 'xiaoliu', 'content' => 'hahahaha'], ['name' => 'xiaoliu', 'content' => 'hahahaha'], ]; $success = PDO::batchInsert('post', $data)->execute(); // 获得受影响的行数 $affectedRows = PDO::getRowCount(); ~~~ ## 更新 常规更新: ~~~ $set = [ 'num' => 2, 'name' => 'xiaoliu2', ]; $where = [ ['id', '=', 23], ]; $success = PDO::update('post', $set, $where)->execute(); // 获得受影响的行数 $affectedRows = PDO::getRowCount(); ~~~ 自增、自减: ~~~ $set = [ 'num' => ['+', 2], 'num1' => ['-', 1], ]; $where = [ ['id', '=', 23], ]; $success = PDO::update('post', $set, $where)->execute(); // 获得受影响的行数 $affectedRows = PDO::getRowCount(); ~~~ ## 删除 ~~~ $success = PDO::delete('post', [['id', '=', 15]])->execute(); // 获得受影响的行数 $affectedRows = PDO::getRowCount(); ~~~ ## 查询 ### 执行原生 `SQL` >[danger] 请不要直接把参数拼接在 SQL 内执行,带参数的 SQL 请使用参数绑定。 ~~~ $rows = PDO::createCommand("SELECT * FROM `post`")->queryAll(); ~~~ ### 参数绑定 普通参数绑定: ~~~ $sql = "SELECT * FROM `post` WHERE id = :id AND name = :name"; $rows = PDO::createCommand($sql)->bindParams([ 'id' => 28, 'name' => 'xiaoliu', ])->queryOne(); ~~~ `IN`、`NOT IN` 参数绑定: > `PDO` 扩展是不支持绑定数组参数的,所以 WHERE IN 都只能直接 `implode(', ',$array)` 拼接到 SQL 里面,MixPHP 帮你做了这一步,所以只需像下面这样使用。 ~~~ $sql = "SELECT * FROM `post` WHERE id IN (:id)"; $rows = PDO::createCommand($sql)->bindParams([ 'id' => [28, 29, 30], ])->queryAll(); ~~~ ### 查询组合 MixPHP 推崇原生 SQL 查询数据库,但由于原生 SQL 在动态 Where 时,做参数绑定会导致逻辑有些复杂,所以 MixPHP 封装了一个查询组合的功能,方便动态控制 Where 与 自动参数绑定。 用户可将整个 SQL 拆分为多个部分,每个部分可选择使用下例两个参数: - `params` 字段内的值会绑定到对应的sql中。 - `if` 字段的值为 false 时,该段 SQL 会丢弃。 常用查询组合: ~~~ $rows = PDO::createCommand([ ['SELECT * FROM `post`'], ['WHERE id = :id AND name = :name ORDER BY id ASC', 'params' => [ 'id' => $this->id, 'name' => $this->name, ], ], ])->queryAll(); ~~~ 动态 Where 查询组合: ~~~ $rows = PDO::createCommand([ ['SELECT * FROM `post` WHERE 1 = 1'], ['AND id = :id', 'params' => ['id' => $this->id], 'if' => isset($this->id)], ['AND name = :name', 'params' => ['name' => $this->name], 'if' => isset($this->name)], ['ORDER BY `post`.id ASC'], ])->queryAll(); ~~~ >[info] WHERE 1 = 1 是一个小技巧,能避免没有 Where 时 SQL 错误的情况出现。 更复杂的查询组合,包含了: - 动态 Join - 动态 Where - 分页 ~~~ $rows = PDO::createCommand([ ['SELECT *'], ['FROM `post`'], [ 'INNER JOIN `user` ON `user`.id = `post`.id', 'if' => isset($this->name), ], ['WHERE 1 = 1'], [ 'AND `post`.id = :id', 'params' => ['id' => $this->id], 'if' => isset($this->id), ], [ 'AND `user`.name = :name', 'params' => ['name' => $this->name], 'if' => isset($this->name), ], ['ORDER BY `post`.id ASC'], ['LIMIT :offset, :rows', 'params' => ['offset' => ($this->currentPage - 1) * $this->perPage, 'rows' => $this->perPage]], ])->queryAll(); ~~~ ## 查询返回结果集 返回多行,每行都是列名和值的关联数组。 > 没有结果返回空数组。 ~~~ $rows = PDO::createCommand("SELECT * FROM `post`")->queryAll(); ~~~ 返回一行 (第一行)。 > 没有结果返回 false。 ~~~ $row = PDO::createCommand("SELECT * FROM `post` WHERE id = 28")->queryOne(); ~~~ 返回一列。 > 没有结果返回空数组。 ~~~ // 第一列 $titles = PDO::createCommand("SELECT title FROM `post`")->queryColumn(); // 第二列 $titles = PDO::createCommand("SELECT * FROM `post`")->queryColumn(1); ~~~ 返回一个标量值。 > 如果该查询没有结果则返回 false。 ~~~ $count = PDO::createCommand("SELECT COUNT(*) FROM `post`")->queryScalar(); ~~~ 返回一个原生结果集 `PDOStatement` 对象。 > 通常在查询大量结果时,为了避免内存溢出时使用。 ~~~ $result = PDO::createCommand("SELECT * FROM `post`")->query(); while ($item = $result->fetch()) { var_dump($item); } ~~~ ## 返回原生 SQL 语句 `PDO` 扩展是无法获取最近执行的 SQL 的,所以这个功能是 MixPHP 通过参数构建出来的,这个在调试时是非常好用的功能。 ~~~ $sql = PDO::getRawSql(); ~~~ ## 事务 手动事务: ~~~ PDO::beginTransaction(); try { PDO::insert('test', [ 'text' => '测试测试', ])->execute(); PDO::commit(); } catch (\Exception $e) { PDO::rollback(); throw $e; } ~~~ 自动事务:等同于上面的手动事务。 ~~~ PDO::transaction(function () { PDO::insert('test', [ 'text' => '测试测试', ])->execute(); }); ~~~