針對 ThinkPHP 3.x/5.x 在 Nginx 下 PATH_INFO 模式失效、頻繁 404/500 的根因分析與標準化修正。
ThinkPHP 依賴 PATH_INFO 解析模組/控制器/方法,Nginx 需額外配置才能正確提取。
server {
listen 80;
server_name your-domain.com;
root /var/www/project/public; # ThinkPHP 5/6 public 目錄
index index.php index.html;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php/php8.1-fpm.sock; # 或 127.0.0.1:9000
fastcgi_index index.php;
include fastcgi_params;
# 關鍵:正確提取 PATH_INFO
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
# 安全:隱藏敏感目錄
location ~ /\. { deny all; }
location ~ /(runtime|application)/ { deny all; }
}
| 參數 | 說明 |
|---|---|
try_files | 優先嘗試靜態檔案,否則交給 index.php 處理(支援 PATH_INFO) |
fastcgi_param PATH_INFO | 將 Nginx 解析的 path_info 傳給 PHP,ThinkPHP 即可正確路由 |
fastcgi_param SCRIPT_FILENAME | 確保 PHP 接收正確的腳本絕對路徑 |
location / {
if (!-e $request_filename) {
rewrite ^/(.*)$ /index.php/$1 last;
}
}
location ~ \.php { # 注意:去掉 $ 結尾
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
set $path_info "";
set $real_script_name $fastcgi_script_name;
if ($fastcgi_script_name ~ "^(.+?\.php)(/.+)$") {
set $real_script_name $1;
set $path_info $2;
}
fastcgi_param SCRIPT_FILENAME $document_root$real_script_name;
fastcgi_param SCRIPT_NAME $real_script_name;
fastcgi_param PATH_INFO $path_info;
}
關鍵細節:location ~ \.php(無 $),讓 /index.php/foo/bar 也能匹配進入 PHP 處理。
// public/index.php
define('_PHP_FILE_', $_SERVER['SCRIPT_NAME']);
// 或 ThinkPHP 5+
// $_SERVER['PATH_INFO'] = $_SERVER['REQUEST_URI']; // 某些情況下需要
runtime/、cache/ 目錄需 www-data 寫入權限pdo_mysql、mbstring、curl、opensslphp think clear 或刪除 runtime/cache/tail -f /var/log/nginx/error.log 即時觀察// 路由測試:訪問 https://domain.com/index.php/index/index/hello/world
// 控制器
public function hello($name) {
dump($_SERVER['PATH_INFO']); // 應輸出 /index/index/hello/world
return 'Hello, ' . $name;
}
標準化 Nginx 配置 + 正確目錄權限 + 清除快取,能解決 99% 的 ThinkPHP 部署問題。