前言
響應式設計雖普及,但仍有場景需後端區分手機/電腦 (如輕量版頁面、廣告投放、統計分析)。本文系統分析三大主流判斷策略的原理、程式碼、優缺點與最佳實務。
策略一:User-Agent 字串匹配 (最常用、但維護成本高)
function isMobileUA(): bool {
$ua = strtolower($_SERVER['HTTP_USER_AGENT'] ?? '');
$mobilePatterns = [
'mobile', 'android', 'iphone', 'ipad', 'ipod',
'blackberry', 'windows phone', 'opera mini',
'kindle', 'silk', 'playbook', 'bb10'
];
foreach ($mobilePatterns as $pattern) {
if (strpos($ua, $pattern) !== false) return true;
}
return false;
}
| 優點 | 缺點 |
| 實作簡單、無額外依賴 | UA 可偽造、新裝置不斷出現、維護詞庫成本高 |
| 可識別具體裝置/瀏覽器/OS | 部分手機瀏覽器 UA 偽裝為桌面版 |
策略二:HTTP_ACCEPT (MIME 偏好) 分析
function isMobileAccept(): bool {
$accept = $_SERVER['HTTP_ACCEPT'] ?? '';
// WAP 瀏覽器通常優先接受 wml/vnd.wap.xhtml+xml
$wapPos = stripos($accept, 'vnd.wap.wml');
$htmlPos = stripos($accept, 'text/html');
return $wapPos !== false && ($htmlPos === false || $wapPos < $htmlPos);
}
| 優點 | 缺點 |
| 基於瀏覽器能力而非字串,較難偽造 | 智慧型手機同時支援 HTML/WAP,邏輯難以完美區分 |
| Accept 標頭格式複雜,解析易出錯 |
策略三:HTTP_VIA (代理標頭) 檢測 —— 運營商級準確度
function isMobileVia(): bool {
$via = $_SERVER['HTTP_VIA'] ?? '';
// 移動/聯通/電信 WAP 閘道會注入 Via 標頭含 "wap"
return stripos($via, 'wap') !== false;
}
// 範例 Via 值:
// HTTP/1.1 hazz-b-gw001-wap (infox-wisg, huawei technologies) -- 中國移動
// zxwap gateway, zte technologies -- 中國聯通
| 優點 | 缺點 |
| 極難偽造 (需控制運營商閘道) | 僅限走運營商 WAP 閘道的流量 (WiFi/4G 直連無 Via) |
| 準確率極高,可作為強驗證依據 | 無法覆蓋所有手機訪問場景 |
綜合推薦方案:分層判斷
function detectDevice(): string {
// 1. Via 最高優先級 (運營商閘道強特徵)
if (isMobileVia()) return 'mobile';
// 2. User-Agent 次之 (覆蓋 WiFi/4G 直連手機)
if (isMobileUA()) return 'mobile';
// 3. Accept 輔助 (極少數特殊瀏覽器)
if (isMobileAccept()) return 'mobile';
return 'desktop';
}
測試與除錯建議
- 收集真實流量的
HTTP_USER_AGENT、HTTP_VIA、HTTP_ACCEPT 存入資料庫,定期分析覆蓋率。
- 使用
Mobile_Detect 庫 (composer require mobiledetect/mobiledetectlib) 替代自維護 UA 詞庫,社群持續更新。
- 前端配合
navigator.userAgent 傳遞 X-Device-Type 標頭,後端直接信任 (需防偽造)。
總結
單一策略皆有盲區。HTTP_VIA 為最強特徵但覆蓋率低,User-Agent 覆蓋率高但可偽造,HTTP_ACCEPT 為輔助。採用分層判斷 + 定期更新 UA 詞庫 (或引入 Mobile_Detect),並記錄判斷依據供事後稽核,是最務實的工程方案。