mod_rewrite - 如何重定向错误的'漂亮'网址

时间:2011-11-19 00:01:19

标签: php apache .htaccess mod-rewrite url-rewriting

我有一个用PHP编写的网站,为每个项目(类别和搜索页面)创建“漂亮”的网址,像这样,

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

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

我有mod_rewrite服务来自网址的实际内容,如下所示:

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]

到目前为止,每件事都可以,但如果有人登上网址,

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

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

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

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

我搜索了SO并广泛搜索答案,但没有运气。我只使用mod_rewrite进行简单的重定向,例如来自没有www的重定向。与www。而我的理解是暂时的,因此我很难理解如何继续进行。

有人能指出我正确的方向吗?

谢谢大家的帮助。非常感激。我正在努力实现Jon Lin的答案,因为我更熟悉使用php / mysql数据库,并了解它应该如何以及为什么应该工作。我的目标是在星期五之前完成,并在完成后更新此页面。非常感谢,卡尔。

*更新* 我已经实现了Jon Lin的答案,现在我的'漂亮'网址,当错误输入时,现在被重定向到正确或'规范'网址,就像在SO上一样。谢谢Jon和所有贡献的人!

3 个答案:

答案 0 :(得分:2)

我认为你需要两套重写规则才能实现这一目标。

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

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

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

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

或者那些东西......

答案 1 :(得分:1)

简单的馅饼:

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了解如何操作)。

创建一个mapfile,您可以在其中放置所需的所有类别:

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]

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

奥利弗

答案 2 :(得分:0)

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

首先需要将类别和slug传递给请求。有点像:

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参数是否存在,将它们与实际类别进行比较,并在查找{{1 }}。如果其中一个不匹配(或丢失,如果需要),则使用id函数将浏览器重定向到具有正确类别和slug的正确链接:

header()

重定向后,该过程会自行重复,但这一次,view-item.php会看到正确的类别和slug,因此页面可以正常显示。