PHP 沒有內建「取得當前完整 URL」的單一函數,需從 $_SERVER 超全域陣列組合。本文詳細拆解各元件來源、注意事項與最佳實踐。
| 變數 | 說明 | 範例值 |
|---|---|---|
HTTPS | 非空值表示 HTTPS(Apache 為 'on',Nginx 需額外設定) | 'on' / '' |
SERVER_PROTOCOL | 協議版本 | 'HTTP/1.1' |
HTTP_HOST | 客戶端送來的 Host 標頭(含 port,若非標準埠) | 'example.com' / 'example.com:8080' |
SERVER_NAME | 伺服器設定的主機名(需啟用 UseCanonicalName On) | 'example.com' |
SCRIPT_NAME | 當前執行腳本路徑(相對 DocumentRoot) | '/index.php' |
REQUEST_URI | 完整請求 URI(含查詢字串) | '/index.php?page=2&sort=desc' |
QUERY_STRING | 查詢字串(不含 ?) | 'page=2&sort=desc' |
SERVER_PORT | 伺服器埠號 | 80 / 443 / 8080 |
function getCurrentUrl(): string { $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http'; $host = $_SERVER['HTTP_HOST'] ?? ($_SERVER['SERVER_NAME'] ?? 'localhost'); $uri = $_SERVER['REQUEST_URI'] ?? '/'; return $protocol . '://' . $host . $uri; } // 使用範例 echo getCurrentUrl(); // 輸出:https://example.com:8080/path/to/script.php?foo=bar
// 1. 協議 $protocol = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') ? 'https' : 'http'; // 2. 域名(優先 HTTP_HOST,含 port) $host = $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'] ?? 'localhost'; // 3. 腳本路徑(不含查詢字串) $script = $_SERVER['SCRIPT_NAME'] ?? ''; // 4. 查詢字串 $query = $_SERVER['QUERY_STRING'] ?? ''; // 5. 組合完整 URL $fullUrl = $protocol . '://' . $host . $script . ($query ? '?' . $query : ''); // 6. 替代方案:直接用 REQUEST_URI(含查詢字串) $fullUrlAlt = $protocol . '://' . $host . ($_SERVER['REQUEST_URI'] ?? '/');
HTTP_X_FORWARDED_PROTO,真實 IP 在 HTTP_X_FORWARDED_FOR。需信任代理標頭並在 Web 伺服器層設定 SetEnvIf X-Forwarded-Proto https HTTPS=on(Apache)或 proxy_set_header X-Forwarded-Proto $scheme;(Nginx)。HTTP_HOST 已包含埠號(如 example.com:8080),無需額外處理 SERVER_PORT。SCRIPT_NAME 固定為實體腳本(如 /index.php),REQUEST_URI 反映使用者看到的虛擬路徑(如 /article/123),分頁/ canonical 應用 REQUEST_URI。PHP_SELF 安全性:$_SERVER['PHP_SELF'] 可能包含路徑資訊(/index.php/),輸出至 HTML 時必須 htmlspecialchars()。class UrlHelper { public static function current(): string { return self::build( self::protocol(), self::host(), $_SERVER['REQUEST_URI'] ?? '/' ); } public static function protocol(): string { return (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http'; } public static function host(): string { return $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'] ?? 'localhost'; } public static function path(): string { return $_SERVER['SCRIPT_NAME'] ?? '/'; } public static function query(): string { return $_SERVER['QUERY_STRING'] ?? ''; } public static function build(string $protocol, string $host, string $uri): string { return $protocol . '://' . $host . $uri; } // 產生相對路徑(供表單 action、AJAX url 使用) public static function relative(): string { return $_SERVER['REQUEST_URI'] ?? '/'; } // 移除指定查詢參數 public static function withoutQueryParams(array $keys): string { $params = []; parse_str($_SERVER['QUERY_STRING'] ?? '', $params); foreach ($keys as $k) unset($params[$k]); $base = self::path(); return $params ? $base . '?' . http_build_query($params) : $base; } }