【问题标题】:mod_rewrite - how to redirect a mistyped 'pretty' urlmod_rewrite - 如何重定向输入错误的“漂亮”网址
【发布时间】:2012-01-01 16:52:59
【问题描述】:

我有一个用 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]

到目前为止一切正常,但是,如果有人登陆类似的网址,

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 数据库并了解它应该如何工作以及为什么工作。我的目标是在星期五之前完成,完成后会更新此页面。非常感谢,卡尔。

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

【问题讨论】:

  • 是“类别”静态(即不变)还是动态(即您可以拥有像 mysite.com/shirts/slug-for-item-two/2 然后 mysite.com/hammers/slug-for-item-two/3 这样的 URL 等等?
  • 嗨,奥利弗。谢谢你的问题。是的,正如您所描述的那样,类别确实会发生变化。像蛞蝓这样的类别取决于每个项目的 ID。尽管显然许多项目都属于同一类别。比如衬衫、帽子等等。

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


【解决方案1】:

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

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

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

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

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

或者类似的东西......

【讨论】:

    【解决方案2】:

    如鱼得水:

    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
    

    在地图文件中创建简单的条目,例如:

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

    现在用相反的方式做另一个文件:

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

    在地图文件中创建简单的条目,例如:

    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]
    

    这样一来,一切都是动态的,但它(更多)更长并且(有点)更复杂。

    奥利维尔

    【讨论】:

      【解决方案3】:

      这可能是您想要在view-item.php 中实现的东西,而不是尝试使用 mod_rewrite。当您在内容内部生成链接时,您可以使用 ID 来查找类别和 slug。这将是您通常如何生成一个对 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 会看到正确的类别和 slug,因此页面会像正常一样被提供。

      【讨论】:

      • 谢谢你,乔恩。我听从了你的回答。现在工作得很好。非常感谢!
      猜你喜欢
      • 2011-02-04
      • 1970-01-01
      • 2012-10-18
      • 2015-10-04
      • 1970-01-01
      • 2016-06-23
      • 1970-01-01
      • 2016-11-22
      • 2013-05-20
      相关资源
      最近更新 更多