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

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

用PHP-FPM进行VHostconfiguration

<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> 

testing文件:

/path/to/slim/index.php

 <?php echo "slim"; 

/path/to/slim/.htaccess

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

/path/to/slim/hello.php:

 <?php echo "hello"; 

/path/to/symfony/app.php

 <?php echo "symfony"; 

/path/to/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 xxxx: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说我不想标准化Apacheconfiguration,这是一个错字。

我想要标准化Apacheconfiguration)

你的问题是使用<LocationMatch>代理到php-fpm, 检查相应的文件是否存在之前应用到所有的URL。 (顺便提一下, ProxyPassMatch会更优雅地做同样的事情。)引用<Location>上的文档 :

<Location>部分完全在文件系统之外运行。

但是,显然需要在将它传递给php-fpm之前检查PHP文件是否存在。 这可以通过使用<FilesMatch>SetHandler来完成:

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

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

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

还要注意,使用FallbackResource对此没有影响,因为<LocationMatch>具有优先级,并且代理甚至不存在到php-fpm的URI。 它只redirect那些会使用Apache的内置404处理程序的URI,但是这并不像你已经注意到的那样。

乍看之下,你似乎没有在虚拟主机中的AllowOverride指令,所以这是正常的文件没有被读取,我仍然想知道:

如果您有权访问虚拟主机,为什么使用.htaccess? 你只是想使你的生活变得复杂(就像你已经在做的那样)。

忘了.htaccess和所有这些重写指令,并在虚拟主机中添加这个简单的行:

 FallBackResource /index.php 

这将基本上做同样的事情,你所有的5重写指令,在一个单一的行。

关于“ 主要脚本未知 ”,检查fpm必须说什么,你可能会指向错误的path和错误地configurationfpm

请记住,尽可能避免在per-dir上下文中定义您的指令,以避免噩梦和不断的头痛。

你声称像/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选项会发&#x51FA;redirect

我不信任.htaccess ,并将其直接放到服务器的configuration中,在你已经拥有的<LocationMatch "^(.*\.php)$">中,并且在它之前的ProxyPass指令之前。