在 Web 開發中,常需將當前頁面完整 URL(含多個查詢參數)作為「返回地址」傳遞給登出、登入或第三方回調介面。例如當前頁面為:
https://xxx/module.php?module=groupbook&view=index&id=2
若直接使用 $_SERVER['REQUEST_URI'] 獲取並拼接至目標 URL:
https://xxx/login.php?op=logout&return=https://xxx/module.php?module=groupbook&view=index&id=2
接收端解析 return 參數時,會誤將 &view=index&id=2 視為當前請求的額外參數,導致實際接收到的 return 僅為 https://xxx/module.php?module=groupbook,造成跳轉失敗。
URL 查詢字串以 & 分隔參數。當參數值本身包含 & 時,若未經編碼,伺服器無法區分「參數分隔符」與「參數值的一部分」。
對完整 URL 進行 URL 編碼,將特殊字元(&、=、? 等)轉換為百分號編碼格式:
<?php
$currentUrl = $_SERVER['REQUEST_URI']; // 取得 /module.php?module=groupbook&view=index&id=2
$encodedUrl = urlencode($currentUrl); // 編碼為 %2Fmodule.php%3Fmodule%3Dgroupbook%26view%3Dindex%26id%3D2
$redirectUrl = "https://xxx/login.php?op=logout&return={$encodedUrl}";
header("Location: {$redirectUrl}");
exit;
<?php
// login.php
$returnUrl = urldecode($_GET['return'] ?? '');
// 還原為 /module.php?module=groupbook&view=index&id=2
header("Location: {$returnUrl}");
手動拼接 URL 容易出錯,建議使用內建函式:
$params = [
'op' => 'logout',
'return' => 'https://xxx/module.php?module=groupbook&view=index&id=2',
];
$url = 'https://xxx/login.php?' . http_build_query($params);
// 自動處理所有參數編碼,輸出:
// https://xxx/login.php?op=logout&return=http%3A%2F%2Fxxx%2Fmodule.php%3Fmodule%3Dgroupbook%26view%3Dindex%26id%3D2
/**
* 獲取當前請求的完整絕對 URL(含查詢字串)
*/
function getCurrentFullUrl(): string {
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$host = $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'];
$uri = $_SERVER['REQUEST_URI'] ?? '';
return "{$scheme}://{$host}{$uri}";
}
// 使用
$returnUrl = getCurrentFullUrl();
$loginUrl = 'https://xxx/login.php?' . http_build_query([
'op' => 'logout',
'return' => $returnUrl,
]);
前端跳轉時同樣需編碼:
const currentUrl = window.location.href;
const loginUrl = `https://xxx/login.php?op=logout&return=${encodeURIComponent(currentUrl)}`;
window.location.href = loginUrl;
| 誤區 | 後果 | 正確做法 |
|---|---|---|
| 直接拼接未編碼 URL | 參數截斷、跳轉錯誤 | 必須 urlencode() 或 http_build_query() |
| 雙重編碼 | 解碼後仍帶有編碼字元 | 確保編碼與解碼次數一致,避免巢狀調用 |
使用 rawurlencode() 而非 urlencode() | 空格編碼為 %20 而非 +,部分舊系統不相容 | 表單/查詢字串場景優先 urlencode();路徑段落用 rawurlencode() |
| 忽略 HTTPS 判斷 | 混合內容警告、安全性降低 | 動態偵測 $_SERVER['HTTPS'] 組裝 scheme |
核心原則:任何作為 URL 參數值傳遞的 URL,必須經過完整編碼。採用 http_build_query() 建構目標 URL 可一次性解決所有參數編碼問題,是現代 PHP 開發的推薦做法。配合完整的當前 URL 獲取工具函式,即可構建健壯的跨頁面跳轉機制。