我有一份Concrete5,一个基于PHP的CMS,运行在example.com
。
Concrete5附带以下关于漂亮网址的基本说明(将所有网址重定向到中央index.php
)
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} !^/c5.7
RewriteRule ^.*$ c5.7/$0 [L] # Concrete5 is running in the c5.7/ subdirectory
</IfModule>
非常简单。
现在我有一组采用
形式的网址 /product/{productname}
我需要转发到Concrete5(虚拟)URL
/products/details?name={productname}
当我在浏览器中手动输入URL时,该URL已设置并按预期工作。
所以我在htaccess
文件中添加了一行,现在看起来像这样:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# New rule for products
RewriteCond %{REQUEST_URI} ^/product/
RewriteRule ^product/(.+)$ /products/details?name=$1 [QSA]
RewriteCond %{REQUEST_URI} !^/c5.7
RewriteRule ^.*$ c5.7/$0 [L]
</IfModule>
当我选择随机外部网址作为重定向目标时,我可以确认RewriteRule
被触发。
但无论何时它是如上所述的内部重定向,会发生什么,我在Concrete5中得到404。当我检查传递给它的内容时,我看到了:
REQUEST_URI: /product/my-random-product
QUERY_STRING: name=my-random-product
所以似乎触发了规则并进行了一些重写,但REQUEST_URI保持不变!
为什么?
是因为PHP 7.1是通过CGI运行的吗?
我在书中尝试了很多变化和所有flags,但收效甚微。
答案 0 :(得分:3)
PHP中的REQUEST_URI
与mod_rewrite中的REQUEST_URI
不同,所以你不能这样做。在PHP中,它始终包含原始URL。因此,如果您的CMS正在使用它,则无法像这样更改它。
您应该将CMS设置为使用您想要的网址,而不是像这样尝试扩充CMS的网址重写。
如果您在PHP中检查REDIRECT_URL
,您将看到最后一次重写的URI。
答案 1 :(得分:2)
PHP中的REQUEST_URI始终是原始请求URI。
因为LSerni和SuperDuperApps已经解释过这个问题,所以我不会详细说明。
相反,我提供了一个快速解决方案:修改REQUEST_URI并在PHP中添加name
参数而不是.htaccess
。
将以下代码添加到Concrete5 index.php
的开头,以确保修改REQUEST_URI
在任何Concrete5代码运行之前:
if(preg_match('-^/product/([^?]*)-',$_SERVER['REQUEST_URI'],$matches)){
$_SERVER['REQUEST_URI'] = '/products/details';
$_GET['name'] = $matches[1];
}
答案 2 :(得分:1)
您的设置适用于PHP 7.1计算机(不含Concrete5)。它确实调用了我刚刚放入的脚本,它位于/c5.7/products/details中。所以Apache部分正在工作。
在脚本中,我发现重写前REQUEST_URI
是旧值。
所以它的值是正常并且它没有被重写是一个红色的鲱鱼 - 它不是假设被重写。 404错误必须归因于其他原因。
您的Concrete5路由应该支持真实的URL,而不仅仅是虚拟URL,因为C5的路由依赖于REQUEST_URI。如果是这样,您需要为短网址创建路线
Route::register('/product/{productname}' ...)
和一个适当的控制器来获取参数并调用“旧”控制器。
使用.htaccess的一种可能性可能就是这样,但我不太确定它会起作用,因为REQUEST_URI仍未改变:
# New rule for products
RewriteCond %{REQUEST_URI} ^/product/
RewriteRule ^product/(.+)$ c5.7/products/details?name=$1 [L,QSA]
否则您需要进行外部重定向,这将在浏览器中公开URL:
RewriteRule product/(.*)$ http://.../products/details?name=$1 [QSA]