Mod_rewrite -如何重定向输入错误的'pretty'url


mod_rewrite - how to redirect a mistyped 'pretty' url

我有一个用php编写的网站,为每个项目(在类别和搜索页面上)创建'漂亮'的url,像这样,

mysite.com/category/slug-for-item-one/1
mysite.com/category/slug-for-item-two/2

/category/和/slug/取决于项目的数字id

我有mod_rewrite服务的实际内容从url,像这样:

mysite.com/view-item.php?id=1
mysite.com/view-item.php?id=2

仅使用项目id检索每个项目的内容。

这是我的htaccess:
RewriteEngine on
RewriteRule ^([^/'.]+)/?$ view-item.php?id=$1 [L]
RewriteRule ^([^/'.]+)/([^/'.]+)/?$ view-item.php?pid=$2 [L]
RewriteRule ^([^/'.]+)/([^/'.]+)/([^/'.]+)/?$ view-item.php?id=$3 [L]

到目前为止一切正常,但是,如果有人登陆了一个url,比如

mysite.com/1
mysite.com/catey/slug-for-item-one/1 

mysite.com/category/slug-item-one/1

内容仍然被提供,但我如何自动重置或重定向到规范版本的url,到:

mysite.com/category/slug-for-item-one/1

我已经搜索了SO和谷歌广泛的答案,但没有运气。我只使用mod_rewrite简单的重定向,如从没有www。与www。我的理解是试探性的,因此我正在努力理解目前如何进行。

谁能给我指个正确的方向?

谢谢大家的帮助。感谢。我正在Jon Lin的答案的实现上工作,因为我更熟悉使用php/mysql数据库,并理解它应该如何以及为什么工作。我的目标是在周五完成,完成后会更新这个页面。非常感谢,卡尔。

* UPDATE *我已经实现了Jon Lin的答案,现在我的"漂亮"url,当输入错误时,现在被重定向到正确或"规范"的url,就像在SO上一样。谢谢你乔恩和所有做出贡献的人!

我认为您将需要两组重写规则来完成此操作。

第一组规则将用于向客户端发送301重定向,以确保它们引用了规范的url:

RewriteRule ^/1    /category/slug-for-item-one/1 [R=301,L]

然后是第二组使用透传[PT]来提供内容的规则:

RewriteRule ^([^/'.]+)/([^/'.]+)/([^/'.]+)/?$ view-item.php?id=$3 [PT,L]

易如反掌:

RewriteCond %{REQUEST_URI} ^([^/'.]+)/([^/'.]+)/([^/'.]+)/$
RewriteCond %1 !category
RewriteRule ^([^/'.]+)/([^/'.]+)/([^/'.]+)/$ $1/category/$3/
这意味着:如果请求看起来像category/slug-for-item-two/2 ,那么第一个匹配不是字 category (无论它是什么),然后强制重定向到category/slug-for-item-two/2

请告诉我它是否有效


更新(在你的评论之后):

应该这样做:

创建2个地图文件(参见mod_rewrite.html#rewritemap学习如何做)。

创建一个地图文件,在其中放置您需要的所有类别:

RewriteMap mapcategories '
  dbm:/web/htdocs/yoursite/rewriterules/categories.map

在mapfile中创建如下简单条目:

shirts 1
hats 2
condoms 3
vegetables 4
mother-in-laws 5
...

现在用相反的内容创建另一个文件:

RewriteMap mapcategoriesreverse '
  dbm:/web/htdocs/yoursite/rewriterules/categoriesreverse.map

在mapfile中创建如下简单条目:

1 shirts
2 hats
3 condoms
4 vegetables
5 mother-in-laws
...

接下来是最难的部分:

RewriteCond %{REQUEST_URI} ^([^/'.]+)/([^/'.]+)/([^/'.]+)/$
# The following rule will try to search into the categories map file
# and if not found, assign CATEGORY to "notfound"
RewriteRule ^([^/'.]+)/([^/'.]+)/([^/'.]+)/$ '
    - [QSA,E=CATEGORY:${mapcategories:%1|notfound}]
# if the CATEGORY is not empty and is not found:
RewriteCond %{ENV:CATEGORY} notfound
# do a reverse map to get the *real* category:
RewriteRule ^([^/'.]+)/([^/'.]+)/([^/'.]+)/$ '
    - [QSA,E=CATEGORYREVERSE:${mapcategoriesreverse:%1|notfound}]
# if the CATEGORYREVERSE is not empty and is not found:
RewriteCond %{ENV:CATEGORYREVERSE} notfound
# this should never happen => 404:
RewriteRule . - [R=404,L]
# If reach here = if the CATEGORYREVERSE is not empty
# this means it has properly been found:
RewriteCond %{ENV:CATEGORYREVERSE} !^$
# Inject the right category:
RewriteRule ^([^/'.]+)/([^/'.]+)/([^/'.]+)/$  '
    %{ENV:CATEGORYREVERSE}/$2/$3/ [QSA]

这样一切都是动态的,但它(更)长,(更)复杂。

Olivier

这可能是您想要在view-item.php中实现的东西,而不是尝试使用mod_rewrite。当您在内容内部生成链接时,您可以使用ID来查找类别和标记。这将是你通常如何去生成一个漂亮的SEO友好的链接。

首先需要传递类别并插入到请求中。类似以下语句:

RewriteEngine on
RewriteRule ^([^/'.]+)/?$ view-item.php?id=$1 [L]
RewriteRule ^([^/'.]+)/([^/'.]+)/?$ view-item.php?pid=$2&cat=$1 [L]
RewriteRule ^([^/'.]+)/([^/'.]+)/([^/'.]+)/?$ view-item.php?id=$3&cat=$1&slug=$2 [L]

在view-item.php的顶部,只需检查catslug参数是否存在,并在查找id时将它们与实际的类别和段塞进行比较。如果其中一个不匹配(或者缺少,如果您愿意),那么使用header()函数将浏览器重定向到具有正确类别和段符的正确链接:

header('HTTP/1.1 301 Moved Permanently');
header("Location: " . $correct_url);
exit();

在它们被重定向后,该过程会重复,但这一次,view-item.php看到了正确的类别和段码,因此页面得到了正常的服务。