| 版本 | 函數定義 | 呼叫寫法 | 結果 |
| PHP 5.3- | function foo(&$var) | foo(&$a) | 允許(已棄用警告) |
| PHP 5.4+ | function foo(&$var) | foo($a) | **正確**,由定義端決定傳址 |
| PHP 5.4+ | function foo(&$var) | foo(&$a) | Fatal Error |
核心原則:傳址意圖應在函數簽名宣告,而非呼叫端。
場景一:遞迴函數傳址修改變數
// 舊寫法 (PHP 5.3)
function test($aa, &$bb) {
if ($aa < $bb) { echo $bb--; test($aa, &$bb); }
}
test(3, &$bb); // Fatal Error in 5.4+
// 新寫法:呼叫端移除 &
function test($aa, &$bb) {
if ($aa < $bb) { echo $bb--; test($aa, $bb); } // 這裡也不用 &
}
$bb = 6;
test(3, $bb); // 輸出 5 4 3
場景二:單次呼叫傳址
function test($aa, &$bb) {
if ($aa < $bb) { $bb--; echo $bb; }
}
$aa = 3; $bb = 6;
test($aa, $bb); // PHP 5.3/5.4 皆輸出 5
// test($aa, &$bb); // 5.4 報錯
場景三:內建函數歷史殘留
早期代碼常見 sort(&$arr)、array_push(&$arr, $v)、next(&$arr) 等。**所有內建函數現已統一由定義端決定傳址,呼叫端一律不可加 &**。
快速檢測與批量修正
- 全專案搜尋
&\$(正則 &\s*\$)定位呼叫端傳址。
- 確認對應函數定義已有
&,直接刪除呼叫端的 &。
- 若函數定義**沒有**
& 但呼叫端強制加 &,需評估是否真需傳址(通常不需),改為回傳值或物件封裝。
其他 PHP 5.4+ 重大變更提醒
session_unregister()、session_is_registered()、session_register() 完全移除,改用 $_SESSION 陣列操作。
safe_mode、register_globals、register_long_arrays 移除。
htmlspecialchars()、htmlentities() 預設編碼從 ISO-8859-1 改為 UTF-8。
array_combine()、array_diff() 等空陣列行為統一。
升級檢查清單
# 1. 掃描呼叫端傳址
grep -rn "&\$" --include="*.php" .
# 2. 檢查已移除函數
grep -rn "session_(unregister|is_registered|register)" --include="*.php" .
# 3. 執行測試套件 / 人工驗證核心流程
建議在預演環境完整跑測試後再上線,避免隱性 Bug 爆發。
- 上一篇文章: PHP 實現 Word 轉 HTML:基於 COM 元件呼叫 Microsoft Word 完整方案
- 下一篇文章: PHP Session 鎖機制與並發阻塞深度解析:原理、現象與解決方案
Copyright ©
程式碼之家 All Rights Reserved