【问题标题】:Recursive mod_rewrite for search engine friendly urls搜索引擎友好网址的递归 mod_rewrite
【发布时间】:2009-12-08 14:37:22
【问题描述】:

我一直在通过previous solution 阅读递归 mod_rewrite 问题,这类似于我正在尝试做的事情,不同之处在于我通过 index.php 文件发送所有查询,所以不要需要在查询中指定脚本。

基本上我想在搜索引擎友好的 url 中递归转换任意数量的参数:

example.com/param1/val1/param2/val2/...

到常规查询字符串:

example.com/index.php?param1=val1&param2=val2&...

到目前为止,我的尝试都没有成功:

RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^([^/]+)/([^/]+) $1=$2&%1 [L]
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^(.*)$ index.php?%1 [L]

有人可以提供任何建议吗?

【问题讨论】:

    标签: php apache .htaccess mod-rewrite recursion


    【解决方案1】:

    我从其他问题中复制了解决方案并进行了如下修改:

    RewriteCond %{QUERY_STRING} ^(.*)$
    RewriteRule ^(.*/)?([^/]+)/([^/]+) $1?$2=$3&%1 [L]
    RewriteCond %{QUERY_STRING} ^(.*)$
    RewriteRule ^.*$ index.php?%1 [L]
    

    它的作用几乎相同,除了在第一条规则中,第一个匹配是可选的,而在第二条规则中,匹配是在所有其他对都匹配后剩下的任何内容上。

    对于奇数个参数,第一个参数被忽略。

    请注意,如果您希望有很多参数,您可能需要更改一些设置。

    将类似的内容添加到您的 .htaccess 文件中

    RewriteOptions MaxRedirects=20
    

    和你的 apache conf 文件类似的东西

    LimitInternalRecursion 20
    

    选择您需要允许的任意数量的递归(对)而不是“20”(默认为 10)。

    【讨论】:

    • 它适用于偶数个参数(虽然不能识别奇数)。感谢您的浏览,非常感谢 ;-)
    • dGreaves,我不确定你希望它对奇数个参数做什么。把最后一行的^$改成^.*$,至少不会报错。
    • 秋葵汤,哈哈。我想我可以更清楚。我希望新的编辑能解决您的问题。
    【解决方案2】:

    我知道这是一个非常古老的线程。但是由于这里发布的答案都对我不起作用,我想发布我的答案,以便访问者可以根据需要使用它,所以我在这里回答:

    Options +FollowSymlinks -MultiViews
    RewriteEngine on
    
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^([^/]+)/([^/]+)(/.*)?$ $3?$1=$2 [N,QSA,DPI]
    RewriteRule ^(/[^/]+|[^/]+/|/?)$ /index.php [L,QSA,DPI]
    

    更多详情请查看我在MOD_REWRITE for URL variables, removing empty parameters and using more than 1field for the first and second variables的回答

    【讨论】:

      【解决方案3】:

      是的……

      取自这里的例子:

      http://iirf.codeplex.com/sourcecontrol/changeset/view/62027?projectName=IIRF#981491

      此规则集迭代地将一对 URL 路径段转换为查询字符串 n=v 段。

      # handle case with no query string.  This rule fires the first time through,
      # and converts the first pair of URL path segments to a n=v query string segment.  
      RewriteRule ^/(?!index\.php)([^\?\/]+)/([^\?\/]+)/([^\?]+)$ /$3?$1=$2
      
      # handle the case where there is an existing query string, and more than one pair of 
      # URL path segments remaining. This rule fires potentially multiple times.
      RewriteRule ^/(?!index\.php)([^\?\/]+)/([^\?\/]+)/([^\?]+)\?(.+)$ /$3?$4&$1=$2
      
      
      # Handle the case with a query string, and exactly one pair of URL path segments. 
      # This fires once (last).
      # It fires when there is an even number of segments. 
      RewriteRule ^/(?!index\.php)([^\?\/]+)/([^\?\/]+)\?([^\?]+)$ /help.cfm?$3&$1=$2  [L]
      
      # Handle the case with no query string, and exactly one pair of URL path segments. 
      # This fires once (last).
      RewriteRule ^/(?!index\.php)([^\?\/]+)/([^\?\/]+)$ /help.cfm?$1=$2  [L]
      
      
      # Handle the edge case, where there is an odd number of segments, which is invalid
      # for these purposes. 
      #
      # This fires once, after all the other pairs have been parsed.  In fact the filter
      # cannot know that there is an odd number of segments until it does all the matching.
      # So at the end we see, we have one left over segment, and we 
      # redirect to a 404 page.
      
      RewriteRule ^/(?!index\.php)([^\/\?]+)\?([^\?]+)$ /ResourceNotFound.php  [L]
      
      # Handle the edge case where there is only one segment. This is also an error
      # in this ruleset.
      RewriteRule ^/(?!index\.php)([^\/\?]+)$ /FoundOnlyOneSegment.php  [L]
      

      此规则集可能不是您想要的,但它说明了方法。它不是为 mod_rewrite 开发的,而是为 IIRF 开发的,它是 IIS 的重写器。但是 mod_rewrite 的语法应该相同,所以这些规则应该可以工作。

      我不知道 mod_rewrite 是否具有日志记录功能或命令行测试功能,但 IIRF ,这可以更轻松地查看单个规则的工作方式或集合的结果的规则。

      IIRF 有一个默认为 10 的迭代限制。有一种方法可以将该限制提高到 30,该限制相当高,但仍不是无限的。这意味着它不适用于“任意数量的参数”。它最多可以转换 15 对参数。我不知道 mod_rewrite 是否有类似的限制。

      【讨论】:

        【解决方案4】:

        试试这些规则:

        RewriteCond %{REQUEST_FILENAME} -f
        RewriteRule ^ - [L]
        RewriteRule ^([^/]+)/([^/]+)(/(.*))?$ /$4?$1=$2 [N,QSA]
        RewriteRule ^$ index.php [L]
        

        第一条规则是排除对现有文件的请求。第二条规则将完成这项工作并重写每个名称和值对。而第三条规则是将最终的URI重写为index.php

        【讨论】:

        • 您好,感谢您的回复,这适用于 2 个查询参数,但似乎不能识别更多?
        • Gumbo,我认为你的工作规则应该有 'L' 而不是 'N' 并且在 $4 之前没有斜线:RewriteRule ^([^/]+)/([^/]+)(/(.*))?$ $4?$1=$2 [L,QSA]
        • @bmb:不,必须完全一样。
        猜你喜欢
        • 1970-01-01
        • 2012-02-24
        • 1970-01-01
        • 2013-07-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-18
        • 1970-01-01
        相关资源
        最近更新 更多