在使用Apache和php7.1的测试服务器上,我可以使用类似example.com/news/id/title
的URL它将我重定向到example.com/news.php
但是url仍然是一样的,我可以在斜杠之后使用Parameters。
现在我在现场主持工作,但它已经不起作用了。我尝试使用htaccess重定向,它适用于example.com/news
重定向到example.com/news.php
但如果我在那之后放了什么,我会得到一个404错误。
如何重定向来自/news/id/
到news.php
,我想在哪里读出id?为什么它在我的测试服务器上原生运行?
非常感谢你的提示。
我的实际.htaccess
:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^news/(.*) /news.php/$1 [R=301,NC,L]
听起来你可能与MultiViews有冲突(mod_negotification的一部分(。您需要确保在.htaccess
文件的顶部禁用多视图:
Options -MultiViews
如果启用了MultiViews,并且您请求/news/id/
,那么在mod_rewrite能够重写请求之前,mod_negotification会为/news.php
生成一个内部子请求(没有任何额外的路径信息(。
为什么在我的测试服务器上本机运行?
MultiViews在Apache上默认是禁用的,但是,由于某些原因,许多共享web主机确实启用了它。它使无扩展URL";神奇地";工作而不做任何事情,然而,这可能会创建重复内容(对SEO不利(,并导致与mod_rewrite的意外冲突层出不穷,比如这样。
更新:将指令改为以下内容:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^news/(.*) /news.php/$1 [L]
这在内部重写(与_externally redirects_) all requests that start
/news/to
/news.php/- where
is passed as _path-info_ to
/news.php相反(
不需要检查目标文件是否存在,因为在本例中它是硬编码的。
删除R
标志将导致内部重写。
您需要清除浏览器缓存,因为301(永久(重定向将由浏览器缓存。
如果你需要一个更通用的解决方案,将/<action>/<data>
重写为/<action>.php/<data>
,那么就这样写:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^([^/]+)/(.*) /$1.php/$1 [L]
同样,在检查附加.php
时请求是否映射到文件之前,无需检查请求是否映射至文件。
请注意,这不是使用%{REQUEST_FILENAME}.php
形式的TestString(正如您最初所做的那样(,因为这可能会导致某些请求的重写循环(500错误(。请参阅我对ServerFault上以下问题的回答,该问题将对此进行进一步解释:https://serverfault.com/questions/989333/using-apache-rewrite-rules-in-htaccess-to-remove-html-causing-a-500-error