传统应用程序通过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选项会发出redirect
。
我不信任.htaccess
,并将其直接放到服务器的configuration中,在你已经拥有的<LocationMatch "^(.*\.php)$">
中,并且在它之前的ProxyPass
指令之前。