經典報錯:Warning: mysql_fetch_assoc() expects parameter 1 to be resource, boolean given。本文解析根因——**mysql_query() 失敗返回 false**,並給出防御性編程標準模式。
<?php
$sql = "SELECT * FROM entries ORDER BY dateposted DESC LIMIT 1";
$result = mysql_query($sql); // 可能返回 false
$row = mysql_fetch_assoc($result); // 傳入 false → 報錯
echo $row['subject']; // 後續崩潰
mysql_query() 執行失敗(SQL 語法錯誤、表不存在、連接中斷、權限不足等)返回 false(布爾值),而非資源。mysql_query() 返回**資源**(可正常遍歷),mysql_fetch_assoc() 返回 false 表示無更多行——**這不報錯**。false 給 mysql_fetch_assoc() 時**。<?php
$link = mysqli_connect('localhost', 'user', 'pass', 'db'); // 推薦 mysqli
if (!$link) {
die('連接失敗: ' . mysqli_connect_error());
}
$sql = "SELECT * FROM entries ORDER BY dateposted DESC LIMIT 1";
$result = mysqli_query($link, $sql);
if (!$result) {
// 記錄錯誤 SQL 便於排查
error_log('[SQL ERROR] ' . mysqli_error($link) . ' | SQL: ' . $sql);
echo '暫無數據';
exit;
}
if ($row = mysqli_fetch_assoc($result)) {
echo "{$row['subject']}
";
// ...
} else {
echo '暫無文章';
}
mysqli_free_result($result);
mysqli_close($link);
?>
if (!$link) ...if (!$result) ... **必須在 fetch 前**mysqli_error($link) / mysql_error()mysqli_free_result()prepare()/bind_param(),防注入且避免語法錯誤。mysql_* 函數自 PHP 5.5 棄用,PHP 7.0 移除。新項目**強制使用**:
mysqli_query()、mysqli_fetch_assoc()$pdo->query()、$stmt->fetch(PDO::FETCH_ASSOC)PDO 示例:
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8mb4', 'user', 'pass', [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
$stmt = $pdo->query("SELECT * FROM entries ORDER BY dateposted DESC LIMIT 1");
$row = $stmt->fetch();
if ($row) { /* ... */ } else { echo '暫無文章'; }
?>
總結:永不信任外部資源(DB、API、文件)調用的成功返回值,必須顯式判斷失敗分支,這是防御性編程的鐵律。