PHP 編譯器採用「單次通過」解析:讀取文件 → 詞法分析 → 語法分析 → 生成 opcode。遇到第一個語法錯誤即停止,報錯位置是編譯器「發現不對勁」的位置,而非真正錯誤位置。
經驗法則:報錯行號往往是真實錯誤的後一行或後幾行。
<?php
$b = "somevalue" // 第 2 行:漏掉分號
if ($b == "somevalue") { // 第 3 行
print "Hello world!";
}
?>
報錯: Parse error: unexpected T_IF on line 3
原因: 編譯器讀完第 2 行以為語句未結束,繼續吞噬 token,直到第 3 行看到 if (T_IF) 這個「不應出現在表達式中」的關鍵字才報錯。
| 錯誤信息關鍵字 | 真實原因 | 排查方向 |
|---|---|---|
unexpected T_IF / T_WHILE / T_FOR / T_FUNCTION | 上一行語句未正確結束 (漏 ; 、漏 } 、漏 ) | 檢查報錯行之前的所有語句結束符 |
unexpected '$' (或 'unexpected end of file') | 函數/類/控制結構缺少右大括號 } | 從文件末尾向上找未閉合的 {,縮進規範化 是最強預防 |
Supplied argument is not a valid MySQL result resource | SQL 執行失敗,mysqli_query 返回 false | 1. 複製 SQL 到數據庫客戶端直跑 2. 檢查連接參數 3. 檢查權限 |
Call to undefined function | 擴展未加載、拼寫錯誤、大小寫不一致 (PHP 函數名不區分大小寫但類方法區分) | php -m / phpinfo() 確認擴展 |
Cannot redeclare function/class | 重複 include、同名函數定義 | 改用 include_once / require_once、命名空間隔離 |
<?php
// ❌ 錯誤寫法:不檢查返回值
$res = mysqli_query($link, $sql);
$row = mysqli_fetch_assoc($res); // Warning 如果 $res 為 false
// ✅ 正確寫法:防御性編程
$res = mysqli_query($link, $sql);
if (!$res) {
error_log('SQL Error: ' . mysqli_error($link) . ' | SQL: ' . $sql);
// 返回友好錯誤或拋出異常
throw new RuntimeException('Database query failed');
}
$row = mysqli_fetch_assoc($res);
?>
} 一眼可見。error_reporting(E_ALL)、display_errors=On、log_errors=On。var_dump($var); die; 或 debug_print_backtrace()。echo 大法,單步執行、觀察變量、調用棧一目瞭然。PHP 錯誤信息看似神秘,實則遵循「編譯器視角」邏輯。養成規範縮進、防御性檢查返回值、善用靜態分析與 Xdebug 三大習慣,調試效率可提升 80% 以上。記住:報錯行號是線索,不是答案。