## `Mix\Database\PDOConnection` 组件 该组件用于 MySQL 等关系型数据库的操作,语法简单明了,且具有独特的查询构造方式,可构造任何复杂的SQL。 >[success] 该组件基于 PDO 扩展,[语句预处理](http://php.net/manual/zh/pdo.prepared-statements.php) 将帮助你免于SQL注入攻击。 | 类 | 调用 | 连接方式 | | --- | --- | --- | | Mix\Database\PDOConnection | app()->db | 短连接 | ## 使用方法 ### 插入 ~~~ $data = [ 'name' => 'xiaoliu', 'content' => 'hahahaha', ]; $success = app()->db->insert('post', $data)->execute(); // 获得刚插入数据的id $insertId = app()->db->getLastInsertId(); ~~~ ### 批量插入 ~~~ $data = [ ['name' => 'xiaoliu', 'content' => 'hahahaha'], ['name' => 'xiaoliu', 'content' => 'hahahaha'], ['name' => 'xiaoliu', 'content' => 'hahahaha'], ['name' => 'xiaoliu', 'content' => 'hahahaha'], ]; $success = app()->db->batchInsert('post', $data)->execute(); // 获得受影响的行数 $affectedRows = app()->db->getRowCount(); ~~~ ### 更新 常规更新: ~~~ $set = [ 'num' => 2, 'name' => 'xiaoliu2', ]; $where = [ ['id', '=', 23], ]; $success = app()->db->update('post', $set, $where)->execute(); // 获得受影响的行数 $affectedRows = app()->db->getRowCount(); ~~~ 自增、自减: ~~~ $set = [ 'num' => ['+', 2], 'num1' => ['-', 1], ]; $where = [ ['id', '=', 23], ]; $success = app()->db->update('post', $set, $where)->execute(); // 获得受影响的行数 $affectedRows = app()->db->getRowCount(); ~~~ ### 删除 ~~~ $success = app()->db->delete('post', [['id', '=', 15]])->execute(); // 获得受影响的行数 $affectedRows = app()->db->getRowCount(); ~~~ ### 查询 #### 执行原生 `SQL` >[danger] 请不要直接把参数拼接在 SQL 内执行,带参数的 SQL 请使用参数绑定。 ~~~ $rows = app()->db->createCommand("SELECT * FROM `post`")->queryAll(); ~~~ #### 参数绑定 普通参数绑定: ~~~ $sql = "SELECT * FROM `post` WHERE id = :id AND name = :name"; $rows = app()->db->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 = app()->db->createCommand($sql)->bindParams([ 'id' => [28, 29, 30], ])->queryAll(); ~~~ #### 查询组合 MixPHP 推崇原生 SQL 查询数据库,但由于原生 SQL 在动态 Where 时,做参数绑定会导致逻辑有些复杂,所以 MixPHP 封装了一个查询组合的功能,方便动态控制 Where 与 自动参数绑定。 用户可将整个 SQL 拆分为多个部分,每个部分可选择使用下例两个参数: - `params` 字段内的值会绑定到对应的sql中。 - `if` 字段的值为 false 时,该段 SQL 会丢弃。 常用查询组合: ~~~ $rows = app()->db->createCommand([ ['SELECT * FROM `post`'], ['WHERE id = :id AND name = :name ORDER BY id ASC', 'params' => [ 'id' => $this->id, 'name' => $this->name, ], ], ])->queryAll(); ~~~ 动态 Where 查询组合: ~~~ $rows = app()->db->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 = app()->db->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(); ~~~ ### 使用 MySQL 函数、存储过程 ``` $db = app()->db; $ret = $db->createCommand('select :uuid')->bindParams([ 'uuid' => $db::raw('uuid()'), ])->queryAll(); $ret = $db->batchInsert('test', [ ['text' => 'aaa', 'created_at' => $db::raw('CURRENT_TIMESTAMP()'), 'uuid' => $db::raw('uuid()')], ['text' => 'bbb', 'created_at' => $db::raw('CURRENT_TIMESTAMP()'), 'uuid' => $db::raw('uuid()')], ])->execute(); ``` ### 查询返回结果集 返回多行,每行都是列名和值的关联数组。 > 没有结果返回空数组。 ~~~ $rows = app()->db->createCommand("SELECT * FROM `post`")->queryAll(); ~~~ 返回一行 (第一行)。 > 没有结果返回 false。 ~~~ $row = app()->db->createCommand("SELECT * FROM `post` WHERE id = 28")->queryOne(); ~~~ 返回一列。 > 没有结果返回空数组。 ~~~ // 第一列 $titles = app()->db->createCommand("SELECT title FROM `post`")->queryColumn(); // 第二列 $titles = app()->db->createCommand("SELECT * FROM `post`")->queryColumn(1); ~~~ 返回一个标量值。 > 如果该查询没有结果则返回 false。 ~~~ $count = app()->db->createCommand("SELECT COUNT(*) FROM `post`")->queryScalar(); ~~~ 返回一个原生结果集 `PDOStatement` 对象。 > 通常在查询大量结果时,为了避免内存溢出时使用。 ~~~ $statement = app()->db->createCommand("SELECT * FROM `post`")->query(); while ($item = $statement->fetch()) { var_dump($item); } ~~~ ### 返回原生 SQL 语句 `PDO` 扩展是无法获取最近执行的 SQL 的,所以这个功能是 MixPHP 通过参数构建出来的,这个在调试时是非常好用的功能。 ~~~ $sql = app()->db->getRawSql(); ~~~ ### 事务 手动事务: ~~~ app()->db->beginTransaction(); try { app()->db->insert('test', [ 'text' => '测试测试', ])->execute(); app()->db->commit(); } catch (\Exception $e) { app()->db->rollback(); throw $e; } ~~~ 自动事务:等同于上面的手动事务。 ~~~ app()->db->transaction(function () { app()->db->insert('test', [ 'text' => '测试测试', ])->execute(); }); ~~~