CakePHP 透過 ConnectionManager 管理資料庫連線,內建查詢日誌功能。本文提供多種列印 SQL 方式:Controller/Table/Command 內即時輸出、DebugKit 工具列、永久日誌記錄、生產環境條件式啟用,並說明參數綁定與敏感資料過濾。
use Cake\Datasource\ConnectionManager;
// 取得預設連線的查詢日誌
$log = ConnectionManager::get('default')->getLog();
// 結構:['query' => 'SQL...', 'params' => [...], 'took' => 1.2, 'numRows' => 10]
foreach ($log as $entry) {
// 格式化輸出 (含參數綁定)
$sql = $entry['query'];
if (!empty($entry['params'])) {
$sql = $this->formatQuery($sql, $entry['params']);
}
debug($sql); // CakePHP debug() 輸出到 debug.log 或網頁
}
// 參數綁定格式化輔助
protected function formatQuery(string $query, array $params): string
{
$replacements = [];
foreach ($params as $key => $val) {
$placeholder = is_int($key) ? '?' : ":$key";
$replacements[$placeholder] = $this->quoteValue($val);
}
// 依序替換避免鍵名衝突
$query = preg_replace_callback('/\?|:\w+/', function($m) use (&$replacements) {
return array_shift($replacements) ?? $m[0];
}, $query);
return $query;
}
protected function quoteValue($val): string
{
if (is_null($val)) return 'NULL';
if (is_bool($val)) return $val ? '1' : '0';
if (is_numeric($val)) return (string)$val;
return "'" . str_replace("'", "''", (string)$val) . "'";
}
# composer.json
"require-dev": {
"cakephp/debug_kit": "^4.5"
}
# 啟用
bin/cake plugin load DebugKit
# 瀏覽器右側工具列 → SQL 面板:顯示所有查詢、參數、耗時、回溯堆疊
'Log' => [
'debug' => [
'className' => 'Cake\Log\Engine\FileLog',
'path' => LOGS,
'file' => 'debug',
'levels' => ['notice', 'info', 'debug'],
'url' => env('LOG_DEBUG_URL', null),
],
'queries' => [
'className' => 'Cake\Log\Engine\FileLog',
'path' => LOGS,
'file' => 'queries',
'levels' => ['debug'],
'scopes' => ['queriesLog'], // 對應 Connection logQueries scope
],
],
// 啟用查詢日誌 (bootstrap.php 或 AppController::beforeFilter)
if (Configure::read('debug')) {
ConnectionManager::get('default')->logQueries(true);
// 或特定 scope
ConnectionManager::get('default')->setLogQueries(true);
}
use Cake\Datasource\ConnectionManager;
use Cake\Log\Log;
use Psr\Log\LogLevel;
ConnectionManager::get('default')->setLogger(function ($query, $params, $took) {
if ($took > 100) { // 超過 100ms
Log::write('warning', 'Slow query: ' . $query, [
'scope' => 'slow_queries',
'params' => $params,
'duration_ms' => $took,
'backtrace' => (new \Exception())->getTraceAsString(),
]);
}
});
# 列出所有查詢 (需在 Shell/Command 內)
bin/cake shell -c "ConnectionManager::get('default')->logQueries(true); \$this->loadModel('Users')->find('all')->toArray();"
// 或使用 SQL log shell (社群外掛)
composer require dereuromark/cakephp-ide-helper --dev
bin/cake ide_helper sql_log
| 設定 | 開發環境 | 生產環境 |
|---|---|---|
debug | true | false |
logQueries | true | false (或僅慢查詢) |
| DebugKit | 載入 | 不載入 |
| SQL 參數 | 完整顯示 | 過濾敏感欄位 (密碼、Token、PII) |
| 日誌等級 | debug | warning/error |
// 在自訂 Logger 中
$sensitiveKeys = ['password', 'token', 'secret', 'api_key', 'credit_card', 'ssn'];
$filteredParams = [];
foreach ($params as $k => $v) {
if (in_array(strtolower($k), $sensitiveKeys, true)) {
$filteredParams[$k] = '[REDACTED]';
} else {
$filteredParams[$k] = $v;
}
}
// 使用 $filteredParams 記錄日誌
public function getFullSql(string $query, array $params): string
{
$driver = ConnectionManager::get('default')->getDriver();
// 使用驅動層編譯 (MySQL/PostgreSQL/SQLite 不同)
return $driver->compileQuery($query, $params); // 回傳可直接 EXPLAIN 的 SQL
}
掌握 CakePHP 多層次 SQL 可視化工具:即時 debug() 除錯、DebugKit 介面分析、永久日誌審計、慢查詢自動告警、生產環境敏感資料保護,能大幅提升資料庫效能調優與問題排查效率。