PDO_MYSQL 提供 PDO::MYSQL_ATTR_INIT_COMMAND 常數,允許在建立連線時自動執行指定 SQL,最常見用途是設定連線字元集(SET NAMES utf8mb4),避免每次查詢前手動執行。
<?php
$dsn = "mysql:host=localhost;dbname=my_db;charset=utf8mb4";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
// 關鍵:連線成功後自動執行
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8mb4' COLLATE 'utf8mb4_unicode_ci'"
];
$pdo = new PDO($dsn, 'user', 'password', $options);
| 常數 | 型別 | 說明 |
|---|---|---|
PDO::MYSQL_ATTR_INIT_COMMAND | integer | 連線時自動執行的 SQL,重連時亦會重新執行 |
PDO::MYSQL_ATTR_COMPRESS | integer | 啟用壓縮協定(需客戶端/伺服器支援) |
PDO::MYSQL_ATTR_DIRECT_QUERY | integer | 直接查詢模式(不使用預處理),僅供相容舊代碼 |
PDO::MYSQL_ATTR_FOUND_ROWS | integer | 回傳符合條件行數而非影響行數 |
PDO::MYSQL_ATTR_IGNORE_SPACE | integer | 允許函數名後有空格 |
PDO::MYSQL_ATTR_LOCAL_INFILE | integer | 啟用 LOAD DATA LOCAL INFILE |
PDO::MYSQL_ATTR_MAX_BUFFER_SIZE | integer | 緩衝區最大大小 |
PDO::MYSQL_ATTR_READ_DEFAULT_FILE | integer | 從 my.cnf 讀取參數 |
PDO::MYSQL_ATTR_READ_DEFAULT_GROUP | integer | 讀取 my.cnf 指定群組 |
PDO::MYSQL_ATTR_SSL_CA | integer | SSL CA 憑證路徑 |
PDO::MYSQL_ATTR_SSL_CERT | integer | SSL 憑證路徑 |
PDO::MYSQL_ATTR_SSL_KEY | integer | SSL 私鑰路徑 |
// 方式一:DSN 參數(PHP 5.3.6+,推薦)
$dsn = "mysql:host=localhost;dbname=test;charset=utf8mb4";
// 內部會自動執行 SET NAMES,但無法指定 COLLATE
// 方式二:INIT_COMMAND(完整控制)
$options[PDO::MYSQL_ATTR_INIT_COMMAND] = "SET NAMES 'utf8mb4' COLLATE 'utf8mb4_unicode_ci'";
// 可同時設定時區、SQL_MODE 等
$options[PDO::MYSQL_ATTR_INIT_COMMAND] = "SET NAMES 'utf8mb4'; SET time_zone = '+08:00'; SET SESSION sql_mode = 'STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION'";
MYSQL_ATTR_INIT_COMMAND 僅在 mysqlnd 或 libmysqlclient 驅動支援。charset 參數與 INIT_COMMAND 同時使用時,以 INIT_COMMAND 為準(視驅動實作而定)。function createPdo(): PDO {
$dsn = sprintf(
'mysql:host=%s;port=%d;dbname=%s;charset=utf8mb4',
env('DB_HOST'), env('DB_PORT'), env('DB_NAME')
);
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8mb4' COLLATE 'utf8mb4_unicode_ci'; SET time_zone = '+08:00'",
];
return new PDO($dsn, env('DB_USER'), env('DB_PASS'), $options);
}
善用 PDO::MYSQL_ATTR_INIT_COMMAND 可集中管理連線層級設定(字元集、時區、SQL_MODE),減少重複代碼,確保所有連線行為一致。