輸入 Tom's book's → 入庫前 addslashes() → 數據庫實際存儲 Tom's book's(無反斜杠) → 讀出直接 echo 顯示正常。但開發者困惑:為何不需要 stripslashes() 也能正常顯示?
PHP ≤ 5.3 預設開啟 magic_quotes_gpc = On,會在請求進入腳本前,**自動對 GET/POST/COOKIE 數據執行 addslashes()**。
流程如下:
Tom's book'sTom\'s book\'s(在 $_POST 中)addslashes($_POST['name']) → Tom\\'s book\\'s(雙重轉義)Tom\'s book\'sTom's book's(單反斜杠被解析為字面單引號)echo 顯示正常**結論**:雙重轉義在 MySQL 入庫環節「剛好」抵消,但這是極不穩定的巧合。
; php.ini
magic_quotes_gpc = Off
然後統一使用 預處理語句(Prepared Statements),完全避開手動轉義:
$stmt = $mysqli->prepare("INSERT INTO t(name) VALUES (?)");
$stmt->bind_param('s', $_POST['name']);
$stmt->execute();
function cleanInput(array $data): array {
if (get_magic_quotes_gpc()) {
$data = array_map('stripslashes', $data);
}
return $data;
}
$_POST = cleanInput($_POST);
$_GET = cleanInput($_GET);
$_COOKIE = cleanInput($_COOKIE);
// 之後再用 mysqli_real_escape_string 或預處理
mysql_real_escape_string?SET NAMES utf8mb4)會導致注入繞過(GBK 雙字節漏洞)。phpinfo() 中 magic_quotes_gpc 狀態。$_GET/$_POST/$_COOKIE(如上 cleanInput)。mysql_query / mysqli_query 拼接 SQL 為預處理語句。htmlspecialchars,JS 用 json_encode,URL 用 rawurlencode。**永遠不要用 stripslashes 作為輸出處理**。addslashes/stripslashes 是上世紀的產物,配合 Magic Quotes 產生無數坑。現代 PHP(≥5.4)已移除 Magic Quotes,**預處理語句 + 上下文輸出編碼** 是唯一標準答案。