<?php
$_COOKIE['user.name'] = 'test'; // 設置
echo $_COOKIE['user_name']; // 實際讀取鍵名為 user_name
?>
設置 user.name,實際存儲與讀取鍵名變為 user_name (點號 → 下劃線)。
歷史遺留:PHP 早期支援 register_globals = On,將 $_GET/$_POST/$_COOKIE 等超全局變量自動註冊為全局變量。變量命名規則不允許點號 ($user.name 語法錯誤),因此 PHP 在導入超全局數據時,統一將點號轉換為下劃線。
$_GET$_POST$_COOKIE$_REQUEST$_SERVER (部分鍵名)注意:$_FILES、$_ENV、$_SESSION 不受影響。
<?php
// 測試頁: test.php?user.name=abc
var_dump($_GET); // ['user_name' => 'abc']
var_dump($_COOKIE); // 若 cookie 有 user.name,鍵名為 user_name
register_globals 導致嚴重安全問題:
<?php
// 老代碼
if ($is_admin) { ... } // 未初始化 $is_admin
// 攻擊請求: test.php?is_admin=1
// 直接覆蓋 $is_admin = '1',繞過權限檢查
PHP 5.4 移除 register_globals,PHP 6 計劃中已廢棄。但點號轉換行為為兼容性保留至今。
user_name、user_id$name = $_COOKIE['user_name'];$_COOKIE['user.name'] 永遠不存在php.ini: register_globals = Off (現代 PHP 預設關閉)現代框架 (Laravel/Symfony/ThinkPHP) 的 Request 物件已封裝參數獲取,開發者無需關心底層轉換:
// Laravel
$name = $request->input('user.name'); // 支援點號語法訪問嵌套數據
$name = $request->cookie('user_name'); // 直接獲取 cookie
點號轉下劃線是 PHP 為兼容已廢棄的 register_globals 保留的歷史行為。理解其由來,遵循下劃線命名規範,使用框架封裝層,即可避免相關坑點。