## Mix\Database\Connection::class
該類用于 MySQL 等關系型數據庫的操作,語法簡單明了,且具有獨特的查詢構造方式,可構造任何復雜的SQL。
>[success] 該類基于 PDO 擴展,[語句預處理](http://php.net/manual/zh/pdo.prepared-statements.php) 將幫助你免于SQL注入攻擊
## 依賴注入配置
- [beans/database.php#L32](https://github.com/mix-php/mix-skeleton/tree/v2.1/manifest/beans/database.php#L32)
## 直接獲取連接
除了通過連接池,我們還能直接通過某個依賴配置直接獲取連接實例:
> 由于 manifest.php 中 Connection::class 的依賴配置并沒有設置 name 屬性,因此 name = 命名空間
~~~
/** @var \Mix\Database\Connection $db */
$db = context()->get(\Mix\Database\Connection::class);
~~~
## 插入
~~~
$data = [
'name' => 'xiaoliu',
'content' => 'hahahaha',
];
$success = $db->insert('post', $data)->execute();
// 獲得剛插入數據的id
$insertId = $db->getLastInsertId();
~~~
## 批量插入
~~~
$data = [
['name' => 'xiaoliu', 'content' => 'hahahaha'],
['name' => 'xiaoliu', 'content' => 'hahahaha'],
['name' => 'xiaoliu', 'content' => 'hahahaha'],
['name' => 'xiaoliu', 'content' => 'hahahaha'],
];
$success = $db->batchInsert('post', $data)->execute();
// 獲得受影響的行數
$affectedRows = $db->getRowCount();
~~~
## 更新
常規更新:
~~~
$set = [
'num' => 2,
'name' => 'xiaoliu2',
];
$where = [
['id', '=', 23],
];
$success = $db->update('post', $set, $where)->execute();
// 獲得受影響的行數
$affectedRows = $db->getRowCount();
~~~
>[success] 更新 / 刪除支持 where 的各種 OR / AND / IN / NOT IN / BETWEEN / NOT BETWEEN 組合,與 QueryBuilder 使用方式相同,如:$where = [['id', '=', 1], ['or', ['id', '=', 2]]];
自增、自減:
~~~
$set = [
'num' => ['+', 2],
'num1' => ['-', 1],
];
$where = [
['id', '=', 23],
];
$success = $db->update('post', $set, $where)->execute();
// 獲得受影響的行數
$affectedRows = $db->getRowCount();
~~~
## 刪除
~~~
$where = [
['id', '=', 23],
];
$success = $db->delete('post', $where)->execute();
// 獲得受影響的行數
$affectedRows = $db->getRowCount();
~~~
## 查詢
- 執行原生 `SQL`
>[info] 請不要直接把參數拼接在 SQL 內執行,帶參數的 SQL 請使用參數綁定。
~~~
$rows = $db->prepare("SELECT * FROM `post`")->queryAll();
~~~
- 參數綁定
普通參數綁定:
~~~
$sql = "SELECT * FROM `post` WHERE id = :id AND name = :name";
$rows = $db->prepare($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 = $db->prepare($sql)->bindParams([
'id' => [28, 29, 30],
])->queryAll();
~~~
## 查詢組合
>[success] 可使用 QueryBuilder 替代該功能處理常用 SQL 的生成,而只在復雜 SQL 時使用該方法。
MixPHP 推崇原生 SQL 查詢數據庫,但由于原生 SQL 在動態 Where 時,做參數綁定會導致邏輯有些復雜,所以 MixPHP 封裝了一個查詢組合的功能,方便動態控制 Where 與 自動參數綁定。
用戶可將整個 SQL 拆分為多個部分,每個部分可選擇使用下例兩個參數:
- `params` 字段內的值會綁定到對應的sql中。
- `if` 字段的值為 false 時,該段 SQL 會丟棄。
常用查詢組合:
~~~
$rows = $db->prepare([
['SELECT * FROM `post`'],
['WHERE id = :id AND name = :name ORDER BY id ASC',
'params' => [
'id' => $this->id,
'name' => $this->name,
],
],
])->queryAll();
~~~
動態 Where 查詢組合:
~~~
$rows = $db->prepare([
['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 = $db->prepare([
['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 函數、存儲過程
```
$ret = $db->prepare('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 = $db->prepare("SELECT * FROM `post`")->queryAll();
// 指定返回對象數組
$rows = $db->prepare("SELECT * FROM `post`")->queryAll(\PDO::FETCH_OBJ);
~~~
返回一行 (第一行)。
> 沒有結果返回 false。
~~~
// 默認返回數組
$row = $db->prepare("SELECT * FROM `post` WHERE id = 28")->queryOne();
// 指定返回對象
$row = $db->prepare("SELECT * FROM `post` WHERE id = 28")->queryOne(\PDO::FETCH_OBJ);
~~~
返回一列。
> 沒有結果返回空數組。
~~~
// 第一列
$titles = $db->prepare("SELECT title FROM `post`")->queryColumn();
// 第二列
$titles = $db->prepare("SELECT * FROM `post`")->queryColumn(1);
~~~
返回一個標量值。
> 如果該查詢沒有結果則返回 false。
~~~
$count = $db->prepare("SELECT COUNT(*) FROM `post`")->queryScalar();
~~~
返回一個原生結果集 `PDOStatement` 對象。
> 通常在查詢大量結果時,為了避免內存溢出時使用。
~~~
$statement = $db->prepare("SELECT * FROM `post`")->query();
while ($item = $statement->fetch()) {
var_dump($item);
}
~~~
## 返回 SQL 語句
`PDO` 擴展是無法獲取最近執行的 SQL 的,所以這個功能是 MixPHP 通過參數構建出來的,這個在調試時是非常好用的功能。
~~~
$sql = $db->getLastSql();
~~~
## 返回 SQL 日志
返回一個數組,包含 sql, bindings, time 三個字段。
~~~
$sql = $db->getLastLog();
~~~
## 事務
手動事務:
~~~
$db->beginTransaction();
try {
$db->insert('test', [
'text' => '測試測試',
])->execute();
$db->commit();
} catch (\Exception $e) {
$db->rollback();
throw $e;
}
~~~
自動事務:等同于上面的手動事務,拋出異常時自動回滾。
~~~
$db->transaction(function () use ($db) {
$db->insert('test', [
'text' => '測試測試',
])->execute();
});
~~~
## 長連接超時問題
MySQL 配置文件內的 `interactive_timeout` 與 `wait_timeout` 參數,決定了 sleep 多長時間的連接會被主動 kill,正常情況下是需要用戶自己來處理連接超時的問題,但使用該組件,用戶不需要處理,組件底層已經幫你處理了。
- 歡迎使用 MixPHP
- 安裝說明
- 全棧安裝
- Phar 開發安裝
- 新手教程
- 命令行常識
- 進程管理
- 熱更新
- 全局變量
- 入門須知
- 命名空間
- 自動加載
- 入口文件
- 增改應用
- 核心功能
- 配置 (manifest.php)
- 協程
- 什么是協程
- 開啟協程
- PHP Stream Hook
- xgo + Channel
- WaitGroup + xdefer
- 連接池
- 協程池
- 定時器
- 依賴注入
- 事件調度
- 命令行
- 簡介
- Application
- 創建命令
- 命令參數
- 打印與顏色
- 守護進程
- 后臺運行
- Web/API 應用
- 簡介
- 服務器
- 路由
- 中間件
- 請求
- 文件上傳
- 響應
- 控制器
- 視圖
- Auth
- Session
- 客戶端
- GuzzleHttp
- 調試與錯誤
- 安全建議
- WebSocket 應用
- 簡介
- 服務器
- 客戶端
- JavaScript
- Swoole
- nginx代理
- 60s無消息斷線
- TCP 應用
- 簡介
- 服務器
- 客戶端
- Telnet
- PHP
- Swoole
- UDP 應用
- 簡介
- 服務器
- 客戶端
- NC
- Swoole
- Sync Invoke 同步調用
- 簡介
- 服務器
- 客戶端
- 公共組件
- 驗證器
- 驗證器定義
- 驗證規則
- 靜態調用
- 日志
- 緩存
- 數據庫
- Database
- ConnectionPool
- Connection
- QueryBuilder
- ExecutedEvent
- Redis
- ConnectionPool
- Connection
- CalledEvent
- 常見問題
- 如何利用CPU多核
- 連接多個數據庫
- 使用主從數據庫
- 如何設置跨域
- form-data 上傳文件失敗
- 輸出大于2M的文件失敗 (xlsx)
- 如何接入EasyWeChat
- 升級指導
- 不兼容修改-001
- 不兼容修改-002
- 不兼容修改-003