單一虛擬主機/雲伺服器綁定多個域名(如 example.com、blog.example.com、shop.example.com),需根據訪問域名自動路由到對應子目錄或子應用,實現「一空間、多站點、互不干擾」。
PHP 通過 $_SERVER['HTTP_HOST'] 獲取訪問域名,配合 header('Location: ...') 或內部路由分發請求。
在網站根目錄放置 index.php 作為統一入口:
<?php
// index.php - 多域名分發入口
$host = strtolower($_SERVER['HTTP_HOST']);
// 移除 www. 前綴統一處理
$host = preg_replace('/^www\./', '', $host);
$routes = [
'example.com' => '/main/', // 主站
'blog.example.com' => '/blog/', // 部落格
'shop.example.com' => '/shop/', // 商城
'api.example.com' => '/api/public/', // API 入口
'admin.example.com' => '/admin/public/', // 後台
];
$target = $routes[$host] ?? '/main/'; // 預設導向主站
// 避免重定向循環
$currentPath = rtrim(dirname($_SERVER['SCRIPT_NAME']), '/') . '/';
if (strpos($currentPath, $target) !== 0) {
header('Location: https://' . $host . $target, true, 301);
exit;
}
// 若已在正確目錄,直接包含對應入口
require __DIR__ . $target . 'index.php';
保持 URL 不變,內部 include 對應應用入口:
<?php
// router.php - 內部分發器
$host = strtolower(preg_replace('/^www\./', '', $_SERVER['HTTP_HOST']));
$apps = [
'example.com' => 'main',
'blog.example.com' => 'blog',
'shop.example.com' => 'shop',
];
$appName = $apps[$host] ?? 'main';
$appEntry = __DIR__ . "/apps/{$appName}/public/index.php";
if (file_exists($appEntry)) {
// 設置應用專用常數/配置
define('CURRENT_APP', $appName);
define('APP_BASE_PATH', __DIR__ . "/apps/{$appName}");
// 修正 $_SERVER 讓子應用正常工作
$_SERVER['SCRIPT_NAME'] = '/' . $appName . $_SERVER['SCRIPT_NAME'];
$_SERVER['REQUEST_URI'] = '/' . $appName . $_SERVER['REQUEST_URI'];
require $appEntry;
} else {
http_response_code(404);
echo "Application not found: {$appName}";
}
推薦生產環境使用 Web 伺服器層面處理,PHP 完全感知不到多域名邏輯:
# Nginx 配置片段
server {
listen 80;
server_name example.com www.example.com;
root /var/www/example/main/public;
index index.php;
# ... PHP 處理配置
}
server {
listen 80;
server_name blog.example.com;
root /var/www/example/blog/public;
index index.php;
# ...
}
server {
listen 80;
server_name shop.example.com;
root /var/www/example/shop/public;
index index.php;
# ...
}
/var/www/example/ ├── main/ # 主站應用 │ ├── public/ # Web 根目錄 │ └── src/ ├── blog/ # 部落格應用 │ ├── public/ │ └── src/ ├── shop/ # 商城應用 │ ├── public/ │ └── src/ ├── shared/ # 共用庫、配置 └── router.php # 可選:PHP 層面分發入口
// 在各應用啟動時設置
ini_set('session.name', 'APP_' . strtoupper(CURRENT_APP) . '_SESS');
session_start();
setcookie(..., ['domain' => '.example.com']) 可共享,或各自設置各自子域名/assets/... 或根據 CURRENT_APP 動態生成main_users, blog_posts)*.example.com 覆蓋所有子站| 方案 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
| PHP 重定向 | 簡單、無需 Web 伺服器權限 | URL 變化、多一次請求、SEO 弱 | 虛擬主機無控制權、臨時方案 |
| PHP 內部分發 | URL 不變、邏輯集中 | PHP 處理每請求、需修正 $_SERVER | 共用代碼庫、單入口框架 |
| Web 伺服器分發 | 效能最佳、完全隔離、標準做法 | 需伺服器配置權限 | 生產環境、VPS/雲伺服器、Docker |
現代部署強烈建議方案三:基礎設施層解決路由,應用層專注業務。若受限於虛擬主機,方案二優於方案一。理解原理後,可根據環境靈活選擇。