首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

CakePHP 列印 SQL 語句完整指南:ConnectionManager、DebugKit、Log 追蹤與生產環境安全

     編輯:PHP 相關知識

CakePHP 透過 ConnectionManager 管理資料庫連線,內建查詢日誌功能。本文提供多種列印 SQL 方式:Controller/Table/Command 內即時輸出、DebugKit 工具列、永久日誌記錄、生產環境條件式啟用,並說明參數綁定與敏感資料過濾。

方式一:即時取得並輸出 (Controller/Table/Shell 內)

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) . "'";
}

方式二:DebugKit 工具列 (開發環境必裝)

# composer.json
"require-dev": {
    "cakephp/debug_kit": "^4.5"
}

# 啟用
bin/cake plugin load DebugKit

# 瀏覽器右側工具列 → SQL 面板:顯示所有查詢、參數、耗時、回溯堆疊

方式三:永久記錄到 Log 檔案 (config/app.php)

'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);
}

方式四:自訂 Logger 記錄慢查詢

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

生產環境安全配置

設定開發環境生產環境
debugtruefalse
logQueriestruefalse (或僅慢查詢)
DebugKit載入不載入
SQL 參數完整顯示過濾敏感欄位 (密碼、Token、PII)
日誌等級debugwarning/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 記錄日誌

進階:取得完整 SQL (含參數) 供 EXPLAIN 分析

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 介面分析、永久日誌審計、慢查詢自動告警、生產環境敏感資料保護,能大幅提升資料庫效能調優與問題排查效率。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved