首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP file_exists() 失效常見原因與解決方案:Safe Mode、權限、路徑問題

     編輯:PHP 相關知識

file_exists() 明明檔案存在卻回傳 false,常見於虛擬主機、跨平台部署、權限設定不當等情境。本文整理三大類原因與對應解法。

一、Safe Mode / open_basedir 限制(虛擬主機常見)

現象

  • 檔案確實存在,file_exists()、is_file()、is_dir() 全部回傳 false。
  • include/require 卻能正常載入同一檔案。

原因

PHP safe_mode(已移除於 PHP 5.4)或 open_basedir 限制了腳本可存取的目錄範圍。若檔案路徑不在允許清單中,檔案系統函數會被阻擋,但 include 例外允許。

解法:使用 $_SERVER['DOCUMENT_ROOT'] 組合絕對路徑

<?php
// 錯誤:相對路徑可能不在 open_basedir 內
$file = 'config.php';
if (file_exists($file)) { ... }

// 正確:組合網站根目錄絕對路徑
$file = $_SERVER['DOCUMENT_ROOT'] . '/config.php';
if (file_exists($file)) { ... }

// 適用於 is_file、is_dir、is_readable 等
if (is_file($_SERVER['DOCUMENT_ROOT'] . '/data/backup.sql')) { ... }
?>

原理: DOCUMENT_ROOT 通常在 open_basedir 允許範圍內,組合出的絕對路徑能通過檢查。

二、檔案/目錄權限不足(Linux 部署常見)

現象

  • 本地 Windows 開發正常,部署到 Linux 伺服器後 file_exists() 失效。
  • 檔案由 Windows 複製或 Git checkout 而來,擁有者/群組為 root 或其他用戶,PHP-FPM 執行用戶(如 www-data)無讀取權限。

解法:修正權限

# 遞歸授予讀取/執行權限(目錄需 x 才能進入)
chown -R www-data:www-data /var/www/html
find /var/www/html -type d -exec chmod 755 {} \;
find /var/www/html -type f -exec chmod 644 {} \;

# 或僅針對特定目錄
chmod -R 755 /var/www/html/storage
chmod -R 755 /var/www/html/public/uploads

注意: 避免使用 777,生產環境嚴禁。

三、路徑字串問題(跨平台、編碼、符號)

問題範例修正
相對路徑基準錯誤file_exists('data/file.txt') 在 include 檔中執行時基準不同使用 __DIR__ . '/data/file.txt' 或 dirname(__FILE__)
目錄分隔符Windows \、Linux / 混用統一用 DIRECTORY_SEPARATOR 或 /(PHP 可跨平台解析 /)
中文檔名編碼Windows GBK、Linux UTF-8,file_exists('中文.txt') 失敗確保 PHP 檔案儲存為 UTF-8,檔案系統亦為 UTF-8;必要時 iconv('UTF-8','GBK',$path)
符號連結file_exists('/path/link') 回傳 true,但 is_file() 視目標類型用 is_link()、readlink() 區分
大小寫敏感Linux 區分大小寫,Windows 不區分實際檔名大小寫與代碼一致

四、快速診斷腳本

<?php
function diagnose($path) {
    echo "檢查: $path\n";
    echo "file_exists: " . (file_exists($path) ? 'true' : 'false') . "\n";
    echo "is_file: " . (is_file($path) ? 'true' : 'false') . "\n";
    echo "is_dir: " . (is_dir($path) ? 'true' : 'false') . "\n";
    echo "is_readable: " . (is_readable($path) ? 'true' : 'false') . "\n";
    echo "realpath: " . (realpath($path) ?: 'false') . "\n";
    echo "perms: " . substr(sprintf('%o', fileperms($path)), -4) . "\n";
    echo "owner: " . posix_getpwuid(fileowner($path))['name'] . "\n";
    echo "php user: " . get_current_user() . "\n";
    echo "open_basedir: " . ini_get('open_basedir') . "\n";
    echo "---\n";
}

diagnose(__DIR__ . '/test.txt');
diagnose($_SERVER['DOCUMENT_ROOT'] . '/test.txt');

五、最佳實踐總結

  1. 永遠使用絕對路徑:__DIR__、$_SERVER['DOCUMENT_ROOT']、realpath()。
  2. 部署腳本自動修正權限:CI/CD 流程加入 chown/chmod 步驟。
  3. 避免在 PHP 代碼中硬編碼路徑:使用設定檔或環境變數。
  4. 檢查 open_basedir:php -i | grep open_basedir 確認限制範圍。
  5. 測試環境模擬生產用戶:sudo -u www-data php diagnose.php。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved