PHP 中獲取「當前檔案路徑」、「執行腳本路徑」、「專案根目錄」、「Document Root」等資訊,常用魔術常數、$_SERVER 超全域陣列與內建函式。本文系統整理各種方法的差異、適用場景與陷阱,附完整對照表。
核心方法分類
一、魔術常數 (編譯時解析,不受 include 影響)
| 常數 | 說明 | 範例輸出 | 備註 |
__FILE__ | 當前檔案完整絕對路徑 (含檔名) | /var/www/html/project/config.php | PHP 5.3+ 推薦用 __DIR__ 替代 dirname(__FILE__) |
__DIR__ | 當前檔案所在目錄完整絕對路徑 (無檔名) | /var/www/html/project | 等同 dirname(__FILE__),效能更好 |
二、$_SERVER 超全域陣列 (執行時解析,隨執行入口變化)
| 鍵名 | 說明 | 範例輸出 | 適用場景 |
SCRIPT_FILENAME | 當前執行的入口腳本絕對路徑 | /var/www/html/public/index.php | 最可靠的「專案入口」判斷,CLI 下也有效 |
SCRIPT_NAME | 入口腳本相對 Document Root 的路徑 | /public/index.php | 生成當前頁面 URL、表單 action |
PHP_SELF | 同 SCRIPT_NAME (CGI 模式下可能不同,現代極少見) | /public/index.php | 表單 action、相對連結 |
DOCUMENT_ROOT | Web 伺服器設定的文件根目錄 | /var/www/html | 專案根目錄基準、包含檔案基準路徑 |
REQUEST_URI | 完整請求 URI (含查詢字串) | /public/index.php?page=1&sort=desc | 路由解析、分頁連結、Canonical URL |
HTTP_HOST | 請求 Host 標頭 | example.com:8080 | 生成完整 URL、多站點識別 |
三、執行環境相關
| 方法 | 說明 | 範例輸出 | 備註 |
getcwd() | 當前工作目錄 (Current Working Directory) | /var/www/html/project | CLI 下為執行指令的目錄;Web 下通常等於 Document Root,但可能被 chdir() 改變 |
dirname(__FILE__) | 等同 __DIR__ | /var/www/html/project | 舊版相容寫法 |
realpath($path) | 解析相對路徑、符號連結,返回規範化絕對路徑 | /var/www/html/project | 檔案存在時才有效;不存在返回 false |
basename($path) | 取得路徑中的檔名部分 | config.php | 可指定後綴移除:basename($file, '.php') |
關鍵差異對照:__FILE__ vs $_SERVER['SCRIPT_FILENAME']
// 檔案結構:
// /var/www/html/project/
// ├── public/
// │ └── index.php (入口)
// └── src/
// └── Config.php (被 include)
// 在 Config.php 中:
echo __FILE__; // /var/www/html/project/src/Config.php (當前檔案)
echo __DIR__; // /var/www/html/project/src
echo $_SERVER['SCRIPT_FILENAME']; // /var/www/html/project/public/index.php (入口腳本)
echo $_SERVER['DOCUMENT_ROOT']; // /var/www/html/project/public (Web 根目錄)
- __FILE__ / __DIR__:綁定定義位置,適合庫檔案內部引用同目錄資源 (如
require __DIR__ . '/../vendor/autoload.php')。
- SCRIPT_FILENAME:綁定執行入口,適合判斷「是否為 CLI 執行」、「專案根目錄在哪」。
- DOCUMENT_ROOT:Web 伺服器設定值,可能與專案結構不符 (如 Laravel public 目錄)。
實務最佳實踐模式
1. 專案根目錄基準常數 (入口檔案定義)
// public/index.php
define('ROOT_PATH', dirname(__DIR__)); // /var/www/html/project
define('APP_PATH', ROOT_PATH . '/app');
define('CONFIG_PATH', ROOT_PATH . '/config');
define('PUBLIC_PATH', __DIR__);
2. 庫檔案內部相對引用
// src/Database/Connection.php
require __DIR__ . '/../../vendor/autoload.php'; // 相對於當前檔案位置
3. 獲取當前請求完整 URL
function current_url() {
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$host = $_SERVER['HTTP_HOST'];
$uri = $_SERVER['REQUEST_URI'];
return $scheme . '://' . $host . $uri;
}
4. CLI 腳本偵測專案根目錄
// bin/console.php
$root = dirname(__DIR__); // 專案根目錄
chdir($root); // 切換工作目錄,後續 getcwd() 即為專案根目錄
常見陷阱與避坑指南
- include/require 時 __FILE__ 不變:A include B,B 中的
__FILE__ 仍指向 B,這是正確行為。
- symlink 導致路徑不一致:使用
realpath() 解析實際路徑。
- Windows 路徑分隔符:PHP 內部統一接受
/,輸出時 Windows 顯示 \,跨平台請用 DIRECTORY_SEPARATOR 或統一 /。
$_SERVER 在 CLI 模式下缺少 HTTP 相關鍵 (HTTP_HOST, REQUEST_URI 等),SCRIPT_FILENAME、argv、argc 仍可用。
- 舊代碼使用
$HTTP_SERVER_VARS:已棄用,請直接用 $_SERVER。
快速查詢表:我該用哪個?
| 需求 | 推薦方法 | 備選 |
| 當前檔案所在目錄 | __DIR__ | dirname(__FILE__) |
| 專案根目錄 (Web/CLI 通用) | 入口檔案 define('ROOT', dirname(__DIR__)) | dirname($_SERVER['SCRIPT_FILENAME']) (需調整層級) |
| Web Document Root | $_SERVER['DOCUMENT_ROOT'] | |
| 當前請求 URL 路徑 | $_SERVER['REQUEST_URI'] | |
| 生成當前頁完整 URL | 組合 HTTPS、HTTP_HOST、REQUEST_URI | |
| 包含同目錄檔案 | require __DIR__ . '/file.php' | |
| CLI 執行時的工作目錄 | getcwd() (可先 chdir(ROOT)) | |
結語
掌握魔術常數與 $_SERVER 的語義差異,是編寫可移植、可維護 PHP 專案的基礎。原則:庫用 __DIR__,應用入口用 SCRIPT_FILENAME,Web 環境資訊用 $_SERVER。在現代框架 (Laravel, Symfony) 中,這些細節已被封裝為 base_path()、request()->url() 等助手函式,理解底層原理有助於除錯與擴展。