PHP 開發中 80% 的時間在除錯。本文系統整理 30+ 高頻錯誤類別、根因分析、解決方案與預防最佳實踐,涵蓋變數、Session、資料庫、編碼、上傳、效能、部署等面向,助你從「試誤修補」轉向「預防為主」。
error_reporting = E_ALL,display_errors = On;生產環境 display_errors = Off、log_errors = Ondeclare(strict_types=1)、靜態分析| 錯誤 | 原因 | 解決 |
|---|---|---|
Undefined variable | 變數未初始化即使用 | 宣告初始值:$var = null;isset()/?? 檢查 |
Undefined array key/index | 陣列鍵不存在 | $arr['key'] ?? 'default'、array_key_exists()、$_GET['id'] ?? 0 |
Trying to access array offset on value of type null/bool | 對非陣列用 [] 存取 (PHP 8.0+) | 確保變數為陣列:is_array($var) && $var['key'] |
| 無法取得 POST/GET 變數 | register_globals = Off (PHP 5.4+ 移除) | **務必用超全域陣列**:$_POST['name']、$_GET['id']、$_REQUEST (不推薦) |
| 錯誤 | 原因 | 解決 |
|---|---|---|
session_start(): headers already sent | Session 前有輸出 (空白、BOM、echo) | session_start() 放**最頂端**,檔案無 BOM、無前置空白 |
| Session 變數跨頁遺失 | Cookie 被禁用、域名/路徑不匹配、session.save_path 無權限 | 檢查 session.cookie_domain、session.save_path 權限、HTTPS 下 session.cookie_secure=1 |
session_start(): open(/tmp/sess_...) failed | 儲存目錄不存在/不可寫 | 建立目錄並給權限:mkdir('/var/lib/php/sessions', 0777, true) 或設定 session.save_path |
| 錯誤 | 原因 | 解決 |
|---|---|---|
SQLSTATE[HY000] [2002] Connection refused | MySQL 服務未啟動、Host/Port 錯誤、防火牆 | 檢查服務狀態、netstat -tlnp | grep 3306、DSN 正確性 |
SQLSTATE[42000]: Syntax error | SQL 語法錯誤、保留字未跳脫 | **使用參數綁定** (Prepared Statements);識別字加反引號 `table` |
PDOException: could not find driver | 缺少 pdo_mysql/mysqli 擴展 | docker-php-ext-install pdo_mysql 或 apt install php-mysql |
| 中文亂碼 | 連線編碼未設定 | DSN 加 charset=utf8mb4 或 $pdo->exec("SET NAMES utf8mb4") |
header("Content-Type: text/html; charset=UTF-8")<meta charset="UTF-8">utf8mb4 + utf8mb4_unicode_cimb_internal_encoding('UTF-8')| 錯誤碼 | 常數 | 原因 |
|---|---|---|
| 1 | UPLOAD_ERR_INI_SIZE | 超過 upload_max_filesize |
| 2 | UPLOAD_ERR_FORM_SIZE | 超過表單 MAX_FILE_SIZE |
| 3 | UPLOAD_ERR_PARTIAL | 部分上傳 (網路中斷) |
| 4 | UPLOAD_ERR_NO_FILE | 未選檔案 |
| 6 | UPLOAD_ERR_NO_TMP_DIR | 缺 upload_tmp_dir 或權限 |
| 7 | UPLOAD_ERR_CANT_WRITE | 寫入暫存失敗 (磁碟滿/權限) |
解決:設定 upload_tmp_dir、目錄權限、post_max_size > upload_max_filesize、驗證 $_FILES['file']['error'] === UPLOAD_ERR_OK
Cannot modify header information - headers already sent → 同 Session 錯誤,輸出前設定 Headerheader("Location: ...") 後**必須** exit,否則腳本繼續執行Allowed memory size exhausted:ini_set('memory_limit', '256M')、分批處理、Generator、unset 大變數Maximum execution time exceeded:set_time_limit(0) (CLI)、分批、佇列非同步Class not found:composer dump-autoload、檢查 composer.json autoload 區塊、命名空間對應composer why-not pkg/name version 分析function debug(mixed $var, string $label = '', bool $die = false): void {
if (php_sapi_name() === 'cli') {
fwrite(STDERR, ($label ? "[$label] " : '') . print_r($var, true) . "\n");
} else {
echo "";
echo ($label ? "[$label]\n" : '');
var_dump($var);
echo "";
}
if ($die) exit;
}
xdebug,設定 xdebug.mode=debug、xdebug.client_host=host.docker.internal// php.ini
log_errors = On
error_log = /var/log/php/error.log
error_log = syslog (系統日誌)
生產環境接入 ELK / Loki / Datadog 等日誌平台。
vendor/bin/phpstan analyse src --level=5vendor/bin/psalm --show-info=falsedeclare(strict_types=1) 每個檔案頂端filter_var、assert()、Value Object、DTO除錯心法:
1. **錯誤訊息是朋友**,完整閱讀堆疊追蹤
2. **最小複現**,隔離問題最小單元
3. **假設驗證**,用斷點/日誌證實/推翻假設
4. **修正根因**,而非掩蓋症狀 (如@抑制錯誤)
5. **沉澱文檔**,將踩坑轉化為團隊規範與工具