在電商分類頁、後台管理列表等場景,常需根據使用者選擇的多重條件(價格區間、品牌、規格…)動態產生分頁連結、保留篩選狀態。本文介紹如何利用 $_SERVER 超全域變數,可靠地取得當前 URL 路徑與查詢字串,並示範多條件篩選的實作邏輯。
| 變數 | 含義 | 範例(假設 URL:https://example.com/list?cat=phone&price=1000-5000&page=2) |
|---|---|---|
$_SERVER['REQUEST_URI'] | 完整請求 URI(含查詢字串) | /list?cat=phone&price=1000-5000&page=2 |
$_SERVER['QUERY_STRING'] | 查詢字串(不含 ?) | cat=phone&price=1000-5000&page=2 |
$_SERVER['SCRIPT_NAME'] | 目前執行腳本路徑 | /list.php 或 /index.php |
$_SERVER['PHP_SELF'] | 目前腳本檔名(相對 DocumentRoot) | /list.php |
$_SERVER['HTTP_HOST'] | 主機名稱 | example.com |
$_SERVER['HTTPS'] | 是否 HTTPS('on' 或未設定) | on |
<?php
function getBaseUrl(): string
{
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$host = $_SERVER['HTTP_HOST'];
$script = $_SERVER['SCRIPT_NAME']; // 或 PHP_SELF
// 取得查詢字串並移除 page 參數
$query = $_SERVER['QUERY_STRING'] ?? '';
parse_str($query, $params);
unset($params['page']); // 移除分頁參數
$newQuery = http_build_query($params);
$url = "$scheme://$host$script";
if ($newQuery !== '') {
$url .= '?' . $newQuery;
}
return $url;
}
// 使用範例
$baseUrl = getBaseUrl();
// 輸出:https://example.com/list?cat=phone&price=1000-5000
<?php
// 1. 定義允許的篩選參數白名單(防止注入)
$allowedFilters = ['cat', 'brand', 'price_min', 'price_max', 'sort'];
// 2. 取得並過濾 GET 參數
$filters = array_intersect_key($_GET, array_flip($allowedFilters));
// 3. 建構 SQL WHERE 子句(示範 PDO 參數綁定)
$whereClauses = [];
$params = [];
foreach ($filters as $key => $value) {
if ($value === '') continue;
switch ($key) {
case 'cat':
$whereClauses[] = 'category_id = :cat';
$params[':cat'] = $value;
break;
case 'brand':
$whereClauses[] = 'brand_id = :brand';
$params[':brand'] = $value;
break;
case 'price_min':
$whereClauses[] = 'price >= :pmin';
$params[':pmin'] = (float)$value;
break;
case 'price_max':
$whereClauses[] = 'price <= :pmax';
$params[':pmax'] = (float)$value;
break;
case 'sort':
// 白名單驗證排序欄位
$allowedSort = ['price_asc', 'price_desc', 'newest'];
if (in_array($value, $allowedSort, true)) {
// 稍後處理 ORDER BY
}
break;
}
}
$whereSql = $whereClauses ? 'WHERE ' . implode(' AND ', $whereClauses) : '';
// 4. 分頁參數
$page = max(1, (int)($_GET['page'] ?? 1));
$perPage = 20;
$offset = ($page - 1) * $perPage;
// 5. 執行查詢(略)
// 6. 產生分頁連結(保留篩選條件)
$baseUrl = getBaseUrl(); // 見上一節
$paginationLinks = [];
for ($p = 1; $p <= $totalPages; $p++) {
$paginationLinks[] = sprintf(
'%d',
$baseUrl,
$baseUrl === '' || strpos($baseUrl, '?') === false ? '?' : '&',
http_build_query(['page' => $p]),
$p
);
}
rawurlencode() 編碼參數值,http_build_query() 會自動處理。parse_str() 遇到同名參數會保留最後一個,若需支援多值(如 brand[]=1&brand[]=2),請在表單名稱加 [] 並用 $_GET['brand'] 取得陣列。pushState)實現無刷新篩選,URL 仍可分享、重新整理。掌握 $_SERVER 變數與 parse_str/http_build_query 的組合,就能輕鬆實現「保留篩選狀態的分頁」、「動態產生分享連結」等常見需求。記得:白名單過濾 + 參數化查詢 + URL 編碼 是安全實作的三寶。