在 php-fpm 处理之前将所有 *.php 重写为单个 index.php(apache)

在 php-fpm 处理之前将所有 *.php 重写为单个 index.php(apache)

通过将旧版 PHP 文件请求传递到 .htaccess 文件中的 index.php,旧版应用程序将通过 Slim 框架传递。此外,在文件夹中设置 Symfony 应用程序并设置别名。

使用 PHP-FPM 的 VHost 配置

<VirtualHost *:80>
    ServerName example.com
    DocumentRoot /path/to/app/slim
    Alias /system /path/to/app/symfony
    <IfModule mpm_itk_module>
            AssignUserId web_user web_user
    </IfModule>
    <LocationMatch "^(.*\.php)$">
            ProxyPass fcgi://127.0.0.1:9001/path/to/app/slim
    </LocationMatch>
</VirtualHost>

测试文件:

/路径/到/slim/index.php

<?php echo "slim";

/路径/到/slim/.htaccess

RewriteEngine On
RewriteBase /    
RewriteRule ^hello$ /hello.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

/路径/到/slim/hello.php:

<?php echo "hello";

/路径/到/symfony/app.php

<?php echo "symfony";

/路径/到/symfony/.htaccess:

DirectoryIndex app.php
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$
    RewriteRule ^(.*) - [E=BASE:%1]
    RewriteCond %{HTTP:Authorization} .
    RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

    RewriteCond %{ENV:REDIRECT_STATUS} ^$
    RewriteRule ^app\.php(?:/(.*)|$) %{ENV:BASE}/$1 [R=301,L]

    RewriteCond %{REQUEST_FILENAME} -f
    RewriteRule ^ - [L]

    RewriteRule ^ %{ENV:BASE}/app.php [L]
</IfModule>


Test Uri                 Expected Output           Actual Output

/hello.php               hello                     hello
----------------------------------------------------------------------
/test                    slim                      slim
----------------------------------------------------------------------
/test.php                slim                      404 error
                                                   [proxy_fcgi:error] [pid 18527] [client x.x.x.x:45357] AH01071: Got error 'Primary script unknown\n'
----------------------------------------------------------------------
/system/hello            symfony                   symfony
/system/app.php/hello    symfony                   symfony

我在 Ubuntu 16 和 CentOs 7 上都尝试过,结果相同。使用 Apache 2.4,AllowOverride All 和 mod_rewrite 启用。PHP7-fpm

我还尝试了什么:

1)ProxyPass fcgi://127.0.0.1:9001/path/to/app/slim/index.php

/test.php 显示“slim”,但是该请求在 slim 框架中被误解为“/”。

根据Apache 文档 .htaccess应先进行处理。

解决这个问题的最佳方法是什么?

(注:Bounty 说我不想标准化 Apache 配置。这是一个打字错误。

我确实想标准化 Apache 配置)

答案1

您的问题是使用<LocationMatch>php-fpm 进行代理,该代理适用于所有 URL检查相应的文件是否存在。(ProxyPassMatch顺便说一下,这样做会更优雅。)引用文档<Location>

<Location>部分操作完全在文件系统之外。

然而你显然想要在将 PHP 文件传递​​给 php-fpm 之前检查该文件是否存在。这可以通过使用<FilesMatch>SetHandler反而:

<FilesMatch \.php$>
    SetHandler "proxy:fcgi://127.0.0.1:9001/"
</FilesMatch>

(我自己在这里使用 unix 套接字,如我上面链接到的文档中所述,所以我不能 100% 确信这是 URL 的正确语法。)

这样,只有文件将被重定向到 php-fpm,并且当相应文件不存在时,您的 mod_rewrite 规则甚至有可能被应用于以 .php 结尾的 URI。

还要注意,使用FallbackResource对此没有影响,因为再次具有<LocationMatch>优先级,甚至将不存在的 URI 代理到 php-fpm。它仅重定向那些原本会使用 Apache 内置 404 处理程序的 URI,但正如您已经指出的那样,这不会启动。

答案2

乍一看,您似乎在虚拟主机中没有 AllowOverride 指令,因此文件未被读取是正常的,但我仍然想知道:

如果您可以访问虚拟主机,为什么还要使用 .htaccess?您只是想用它让自己的生活更复杂(您似乎已经这样做了)。

忘记.htaccess 和所有那些重写指令并在您的虚拟主机中添加这行简单的代码:

FallBackResource /index.php

这实际上将在一行中完成所有 5 个重写指令所执行的相同操作。

关于 ”主要脚本未知“,检查 fpm 所说的内容,你可能指向路径错误,fpm 配置不正确

请记住尽可能避免在每个目录上下文中定义指令,以避免噩梦和持续的头痛。

答案3

您声称请求就像/test工作,但/test.php事实并非如此。

发生这种情况时,是否总是/test.php不存在,并且请求以 结尾.php? 如果是这样,您可以做的是指示浏览器自动发出另一个请求,剥离该.php部分。

可以通过以下方式实现:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.*)\.php$ $1 [R]

按照http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewriterule,该R选项将发出一个redirect

我不会信任.htaccess,并将其直接放入服务器的配置中,在<LocationMatch "^(.*\.php)$">您已经拥有的配置中,并在其中的指令之前ProxyPass

相关内容