symfony 2在nginx下实现伪静态并由其接管404,关键在于配置try_files $uri /app.php?$query_string将非静态请求交由app.php处理,同时禁止直接访问app.php、正确设置script_filename和$realpath_root确保路径解析准确,并保证静态资源可直读、不触发nginx 404。

Symfony 2 在 Nginx 下要正确处理伪静态(即隐藏 app.php)并让 404 由 Symfony 自身接管,关键在于 Nginx 配置必须满足两个条件:一是将所有非静态资源请求全部转发给 app.php(或 app_dev.php),二是确保静态文件(如 CSS、JS、图片)能被直接读取,不经过 PHP;同时,Nginx 不能提前返回 404,而应把路径不存在的判断交给 Symfony 的路由系统。
核心 Nginx 配置要点
Nginx 不像 Apache 默认支持 .htaccess,需在 server 块中显式定义重写逻辑。以下是最简但完整的生产环境配置片段(以 web/ 为文档根目录):
- 用
try_files优先尝试匹配真实文件(如/css/app.css),命中则直接返回;未命中则交由app.php处理 - 禁止直接访问
app.php或app_dev.php的 URL(防止绕过缓存或暴露开发入口) - 明确设置
SCRIPT_FILENAME和fastcgi_param,确保 PHP-FPM 能正确解析请求路径
推荐的 server 配置示例
以下配置适用于 Symfony 2.8+(web/ 为 root):
location / {
try_files $uri /app.php?$query_string;
}
<h1>防止 app.php 被直接访问</h1><p>location ~ ^/(app|app_dev|config).php(/|$) {
return 404;
}</p><h1>PHP 处理块(通常单独 include 或内联)</h1><p>location ~ .php$ {
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; # 根据实际调整
fastcgi_split_path_info ^(.+.php)(/.+)$;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
include fastcgi_params;
}</p>
注意:$realpath_root 是关键——它确保软链接(如 web -> ../public)也能正确解析物理路径,避免 file not found 错误。
为什么 404 还是 Nginx 返回的?
常见原因有三个:
-
try_files没写对,比如漏掉$query_string,导致 GET 参数丢失,Symfony 路由匹配失败后可能因异常退出而非返回 404 页面 - 静态资源路径错误(如
assets/目录权限不足或未部署),Nginx 找不到文件且未 fallback 到app.php,直接返回 404 - 开发环境下未启用
debug模式,或app_dev.php中未设置debug = true,导致异常被静默吞掉,看起来像空白页或 Nginx 404
Symfony 端需确认的配置
确保以下两点已启用:
-
kernel.debug为true(开发环境),且app_dev.php中未注释掉Debug::enable() - 自定义 404 页面已存在:
app/Resources/TwigBundle/views/Exception/error404.html.twig或app/Resources/views/Exception/error404.html.twig - 路由配置无误,特别是没有全局
defaults覆盖了 404 行为;可临时加一条catch-all路由验证是否进到控制器











