PHP 專案中正確取得檔案系統路徑與網址 URL 是基礎技能。本文系統整理各種方法、適用場景、常見陷阱與現代最佳實務。
檔案系統路徑 (伺服器端絕對路徑)
| 方法 | 回傳值範例 | 適用場景 | 注意事項 |
__DIR__ | /var/www/html/project/src | 當前檔案所在目錄 (推薦) | PHP 5.3+,編譯時期常數 |
__FILE__ | /var/www/html/project/src/config.php | 當前檔案完整路徑 | 同 __DIR__ |
dirname(__FILE__, 2) | /var/www/html/project | 向上 N 層目錄 | PHP 7.0+ 支援第 2 參數 |
$_SERVER['DOCUMENT_ROOT'] | /var/www/html | Web 根目錄 | 依賴伺服器設定,可能不準 |
getcwd() | /var/www/html/project | 當前工作目錄 | CLI/排程腳本可能不同 |
網址 URL (客戶端可存取)
| 變數 | 範例 | 說明 |
$_SERVER['HTTP_HOST'] | example.com:8080 | Host Header (含港口) |
$_SERVER['SERVER_NAME'] | example.com | 伺服器設定名稱 |
$_SERVER['REQUEST_URI'] | /path/to/page?foo=bar | 完整請求路徑+查詢字串 |
$_SERVER['PHP_SELF'] | /path/to/script.php | 執行腳本路徑 (相對 DocumentRoot) |
$_SERVER['SCRIPT_NAME'] | /path/to/script.php | 同 PHP_SELF,較標準 |
$_SERVER['HTTPS'] | on / 空值 | 判斷 HTTPS |
組合完整 URL
<?php
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;
}
function getBaseUrl(): string {
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$host = $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'] ?? 'localhost';
$scriptName = $_SERVER['SCRIPT_NAME'] ?? '';
return $protocol . '://' . $host . dirname($scriptName);
}
// 範例
// 當前: https://example.com:8080/blog/post?id=123
echo getCurrentUrl(); // https://example.com:8080/blog/post?id=123
echo getBaseUrl(); // https://example.com:8080/blog
?>
現代最佳實務:集中化路徑管理
<?php
// config/paths.php
return [
'root' => dirname(__DIR__), // 專案根目錄
'public' => dirname(__DIR__) . '/public', // Web 公開目錄
'storage' => dirname(__DIR__) . '/storage', // 儲存目錄
'cache' => dirname(__DIR__) . '/storage/cache',
'logs' => dirname(__DIR__) . '/storage/logs',
'uploads' => dirname(__DIR__) . '/storage/uploads',
'config' => dirname(__DIR__) . '/config',
'src' => dirname(__DIR__) . '/src',
'views' => dirname(__DIR__) . '/views',
'vendor' => dirname(__DIR__) . '/vendor',
// URL 相關
'app_url' => $_ENV['APP_URL'] ?? 'https://localhost',
'asset_url' => ($_ENV['APP_URL'] ?? 'https://localhost') . '/assets',
];
// 使用方式
$paths = require __DIR__ . '/config/paths.php';
$uploadPath = $paths['uploads'] . '/avatars/' . $userId . '.jpg';
$avatarUrl = $paths['asset_url'] . '/avatars/' . $userId . '.jpg';
?>
常見陷阱與避坑指南
⚠️ DOCUMENT_ROOT 不可靠
虛擬主機、Docker、反向代理下可能指向錯誤路徑。
✅ 使用 __DIR__ 向上推導專案根目錄。
⚠️ HTTP_HOST 可被偽造
客戶端可任意發送 Host Header。
✅ 生產環境使用信任代理設定或環境變數 APP_URL。
⚠️ CLI 模式無 $_SERVER['REQUEST_URI']
排程腳本、Artisan 指令執行時會報錯。
✅ 判斷 php_sapi_name() === 'cli' 分支處理。
框架整合參考
| 框架 | 專案根目錄 | 公開目錄 |
| Laravel | base_path() | public_path() |
| Symfony | $this->getParameter('kernel.project_dir') | $this->getParameter('kernel.project_dir') . '/public' |
| CodeIgniter 4 | FCPATH (前端控制器目錄) | FCPATH |
| ThinkPHP | app()->getRootPath() | app()->getRootPath() . 'public' |
路徑操作工具函數
<?php
// 安全路徑連接 (防止目錄遍歷)
function safeJoin(string $base, string $relative): string {
$base = rtrim(realpath($base), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
$full = realpath($base . $relative);
if ($full === false || !str_starts_with($full, $base)) {
throw new Exception('路徑超出允許範圍');
}
return $full;
}
// 相對路徑轉絕對 URL
function asset(string $path): string {
$base = rtrim(config('paths.asset_url'), '/');
return $base . '/' . ltrim($path, '/');
}
?>
路徑管理核心原則:檔案系統路徑用 __DIR__ 推導,網址用環境變數設定,集中管理於設定檔,避免硬編碼與 $_SERVER 依賴。