在 PHP 開發中,經常需要從完整 URL 中提取純域名(去除協議、www 前綴、路徑、查詢參數等)。本文介紹一個簡潔健壯的域名解析函數。
<?php
/**
* 從 URL 中提取主域名
* @param string $url 完整 URL
* @return string 域名(不含 www、協議、路徑)
*/
function phpzygetname($url) {
// 1. 正則提取主機部分:匹配協議後到第一個 / 之前的內容
$referer = preg_replace('/https?:\/\/([^\/]+).*/i', '$1', $url);
// 2. 移除 www. 前綴
$referer = str_replace('www.', '', $referer);
return $referer;
}
// 測試示例
$testUrls = [
'https://www.example.com/path/to/page',
'https://sub.domain.org:8080/api?param=value',
'https://localhost:3000/',
'ftp://files.example.net/download/file.zip'
];
foreach ($testUrls as $url) {
echo "URL: $url\n";
echo "域名: " . phpzygetname($url) . "\n\n";
}
?>
/https?:\/\/([^\/]+).*/i
https?://:匹配 https:// 或 https://([^\/]+):捕獲組,匹配非斜杠字符(即域名部分).*:匹配剩餘路徑i:不區分大小寫$1 保留捕獲組內容(域名+端口)<?php
/**
* 專業級域名解析函數
* @param string $url
* @param bool $removeWww 是否移除 www
* @param bool $keepPort 是否保留端口
* @return string|null 解析失敗返回 null
*/
function extractDomain($url, $removeWww = true, $keepPort = false) {
// 使用 PHP 內置 parse_url 更可靠
$parsed = parse_url($url);
if (!$parsed || empty($parsed['host'])) {
return null;
}
$host = $parsed['host'];
// 移除 www 前綴
if ($removeWww && strpos($host, 'www.') === 0) {
$host = substr($host, 4);
}
// 處理端口
if (!$keepPort && isset($parsed['port'])) {
$host = str_replace(':' . $parsed['port'], '', $host);
}
return $host;
}
/**
* 獲取根域名(如 example.com 而非 sub.example.com)
* 需配合公共後綴列表,這裡提供簡易版
*/
function getRootDomain($url) {
$domain = extractDomain($url);
if (!$domain) return null;
$parts = explode('.', $domain);
if (count($parts) <= 2) return $domain;
// 簡易判斷:常見雙級後綴
$tlds = ['com.cn', 'net.cn', 'org.cn', 'gov.cn', 'edu.cn', 'co.uk', 'com.au'];
$lastTwo = strtolower($parts[count($parts)-2] . '.' . end($parts));
if (in_array($lastTwo, $tlds) && count($parts) >= 3) {
return implode('.', array_slice($parts, -3));
}
return implode('.', array_slice($parts, -2));
}
// 測試
$urls = [
'https://www.baidu.com/s?wd=php',
'https://api.github.com/users/octocat',
'https://sub.domain.co.uk:8443/path',
'https://localhost:8080',
'invalid-url'
];
foreach ($urls as $url) {
echo "URL: $url\n";
echo " 域名: " . (extractDomain($url) ?? '解析失敗') . "\n";
echo " 根域名: " . (getRootDomain($url) ?? '解析失敗') . "\n\n";
}
?>
| 方法 | 優點 | 缺點 | 推薦場景 |
|---|---|---|---|
| 正則表達式 | 代碼簡短、無依賴 | 邊界情況處理差、不支持非標準 URL | 簡單腳本、已知格式 URL |
| parse_url() | PHP 內置、標準化、健壯 | 嚴格模式下對異常 URL 可能失敗 | 生產環境、通用 URL 解析 |
| parse_url + 公共後綴列表 | 準確提取根域名 | 需維護後綴列表、體積較大 | 域名分析、Cookie 作用域設置 |
parse_url():PHP 內置函數經過充分測試,符合 RFC 3986 標準parse_url() 失敗時返回 falseidn_to_ascii() 處理TLDExtract)雖然正則表達式能快速實現基本域名提取,但 parse_url() 才是 PHP 中處理 URL 的標準、可靠方式。根據業務需求選擇:簡單提取用內置函數,根域名分析引入專業庫。