我想使用mod_rewrite(在.htaccess中)将"干净"的URL映射到子目录中它们对应的php文件,例如:

https://example.com/test/
-->
https://example.com/p/test.php

我的第一步是给所有没有斜杠的URL添加尾部斜杠:

RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*[^/])$ $1/ [L,R=301]

然后,我添加了以下几行,以确保该路径/文件不存在:

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f

最后是将所请求的路径映射到子目录/p/中的相应文件的RewriteRule:

RewriteRule ^(.+)$ /p/$1\.php

这似乎工作得很好--除非我请求的URL不存在.然后,该操作将导致无限循环,例如:

https://example.com/p/p/p/p/p/p/p/p/p/p/p/p/p/p/p/p/p/p/p/p/p/p/p/p/p/p/p/p/p/p/p/p/p/p/p/p/p/test/.php/.php/.php/.php/.php/.php/.php/.php/.php/.php/.php/.php/.php/.php/.php/.php/.php/.php/.php/.php/.php/.php/.php/.php/.php/.php/.php/.php/.php/.php/.php/.php/.php/.php/.php/.php/.php/

我已经try 在RewriteRule之前再添加RewriteCond,以确保所请求的文件确实存在于子文件夹/p/中,但我的方法不起作用:

RewriteCond %{DOCUMENT_ROOT}/p/$1.php -f

有人能告诉我我做错了什么吗?

推荐答案

我已经try 在RewriteRule之前再添加RewriteCond,以确保所请求的文件确实存在于子文件夹/p/中,但我的方法不起作用:

是的,你需要这样做……判断您想要重写的文件是否确实存在,而不是重写任何根本不存在的内容(如果目标也不存在,这将导致重写循环).然而,您的"问题"是您的URL以斜杠结尾,而您似乎没有在您的规则中考虑到这一点.因此,给定/test/的请求,您实际上是在try 测试%{DOCUMENT_ROOT}/p/test/.php,而%{DOCUMENT_ROOT}/p/test/.php自然是不存在的.

您需要在RewriteRule pattern的捕获子模式中排除尾随斜杠.例如:

# Rewrite "/test/" to "/p/test.php" if it exists
RewriteCond %{DOCUMENT_ROOT}/p/$1.php -f
RewriteRule ^(.+)/$ p/$1.php [L]

不需要额外的文件系统判断(和开销)来判断请求是否没有映射到文件或目录-因为这些应该是互斥的事件.(如果您碰巧有一个同名的目录,则相应的.php文件将无法访问.)

然后,您的完整文件将变为:

RewriteEngine on

# Append trailing slash (if omitted)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+[^/])$ /$1/ [R=301,L]

# Rewrite "/test/" to "/p/test.php" if it exists
RewriteCond %{DOCUMENT_ROOT}/p/$1.php -f
RewriteRule ^(.+)/$ p/$1.php [L]

注意,不需要在规则中附加尾随斜杠的第二个条件来测试请求的URL不以尾随斜杠结尾,因为这已经由RewriteRule pattern处理(如果有尾随斜杠,模式将根本不匹配).

而且这里不需要RewriteBase指令.在外部重定向中,最好是明确的,并在substitution字符串中包括斜杠前缀.


Aside:

我的第一步是给所有没有斜杠的URL添加尾部斜杠:

只是为了澄清一下,你所有的内部链接必须已经更新,以包括尾随斜杠,否则你的用户(和搜索引擎)将不必要地一直被重定向.

Php相关问答推荐

产品ACF值在WooCommerce我的账户订单的附加列中为空

Laravel迁移返回SQL错误,但SQL有效且工作正常

如何让PHP变量跨越多个脚本调用?

PHP中的圆生成器在国际日期变更线上失败

如何修复条带元素中的错误&&客户端_机密&

将一个情态形式放在细丝v3中的形式中间

在Laravel中从动态嵌套数组中获取值

如何在微软图形API中使用用户S访问令牌或基于租户ID的访问令牌?

函数存储到变量中

调用模型[App\Models\Employee]上未定义的关系[title]

Shopware 6 插件:如何删除/迁移布尔配置到多选配置

invalid_grant 和无效的 JWT 签名

如何在 PHP laravel 中将图像的透明背景转换为白色?

如何限制 woocommerce 中相关产品的标题长度

如何显示所有数组数据而不仅仅是最后的结果

在特征中使用类的属性

如何在 php 中获取正确的时间

在 Botiga 主题模板中添加复选框到政策行.Woocommerce

为什么非贪婪匹配会消耗整个模式,即使后面跟着另一个非贪婪匹配

如何通过本地主机在同一台 PC 上同时运行 Microsoft IIS 和 WAMP