有没有更好的方法来做这个正则表达式?

时间:2009-09-21 02:22:33

标签: regex mod-rewrite clean-urls

我终于想出了一个好的/简单的方法,用我在这个格式的网站上用正则表达式创建干净的URL,但是它需要一个非常大的.htaccess文件,我从这里的帖子知道它应该不是使用mod_rewrite对性能有害,但我从来没有真正看到它用于我的方式,几乎每个网站的页面都有一个单独的条目。

下面是一个条目示例,1个页面有2个条目,第一个条目重写

http://www.example.com/users/online/friends/

  http://www.example.com/index.php?p=users.online.friends

它工作得很好但是如果用户不在第一页上,那么在页面上添加了另一个用于分页的东西,当发生这种情况时我不得不写另一个条目进行重写,这是正确的方法还是应该将它们结合起来不知何故?

RewriteRule ^users/online/friends/*$ ./index.php?p=users.online.friends&s=8
RewriteRule ^users/online/friends/(\d+)/*$ ./index.php?p=users.online.friends&s=8&page=$1

第二个会这样做

http://www.example.com/users/online/friends/22/

  http://www.example.com/index.php?p=users.online.friends&page=22

3 个答案:

答案 0 :(得分:3)

是的,没关系。我猜他们可以合并成一条规则,但实际上没有任何需要。

您可以考虑将网页作为网址的一部分,而不是:

http://www.domain.com/users/online/friends/22/

只有:

http://www.domain.com/users/online/friends?page=22

然后有一条规则:

RewriteRule ^users/online/friends/?$ ./index.php?p=users.online.friends&s=8 [L,QSA]

附加查询字符串

编辑:有几种方法可以减少重写规则的数量。

首先,在搜索字词中使用通配符,例如:

RewriteRule ^users/(\w+)/(\w+)$ /index.php?p=users.$1.$2 [L,QSA]

将减少相当多的规则。

其次,如果您通过/index.php传递所有内容,请考虑在那里委派所有请求:

RewriteRule ^(users/*)$ /index.php/$1 [L,QSA]

该规则使用第三种技术:不是通过查询字符串参数传递路径信息,而是通过额外的路径信息传递它。这可以通过$_SERVER['PATH_INFO']访问。

话虽如此,许多规则并不一定是坏事。至少它明确了你的所有行动。你需要注意的是制造维护噩梦。

答案 1 :(得分:3)

这取决于您认为更具可读性的内容,但是您可以通过单一规则来实现这一目标:

RewriteRule ^users/online/friends(/(\d+))?/*$ ./index.php?p=users.online.friends&s=8&page=$2

已编辑更忠实于原始问题中对尾随斜线的处理。是: RewriteRule ^ users / online / friends /((\ d +)/ *)?$。/的index.php p = users.online.friends&安培; S = 8和;页= $ 16

这里我只是说“(...)?”在网址的最后部分周围使其成为可选匹配,并将反向引用更改为$ 2.

当然,这实际上将http://www.domain.com/users/online/friends/重写为:

<强> http://www.domain.com/index.php?p=users.online.friends&page=

因此,您的PHP代码必须检查页面参数是否为非空。

答案 2 :(得分:2)

# Initial step
RewriteCond %{QUERY_STRING} !(?:^|&)p=
RewriteRule ^([^/]+)/(.+) /$2?p=$1 [QSA]

# Subsequent steps
RewriteCond %{QUERY_STRING} ((?:[^&]*&)*?)p=([^&]*)(.*)
RewriteRule ^([^/]+)/(.+) /$2?%1p=%2.$1%3

# Last step with page number
RewriteRule ^(\d+)/?$ /index.php?page=$1 [QSA,L]

# Last step without page number
RewriteCond %{QUERY_STRING} (?:((?:[^&]*&)*?)p=([^&]*))?(.*)
RewriteRule ^([^/]+)/?$ /index.php?%1p=%2.$1%3 [L]

这将通过几个步骤重写URL:

  1. http://www.domain.com/users/online/friends/22/
  2. http://www.domain.com/online/friends/22/?p=users
  3. http://www.domain.com/friends/22/?p=users.online
  4. http://www.domain.com/22/?p=users.online.friends
  5. http://www.domain.com/index.php?p=users.online.friends&page=22
  6. 以下是一种更简单的方法,但需要您更改脚本:

    RewriteRule ^(.*?)(?:/(\d+))?/?$ /index.php?p=$1&page=$2 [QSA,L]
    

    它可以一步完成所有事情,但有一点不同:

    1. http://www.domain.com/users/online/friends/22/
    2. http://www.domain.com/index.php?p=users/online/friends&page=22
    3. 添加s=8查询参数需要更多工作:

      1. 使用每页的菜单编号创建一个文本文件。
      2. 添加RewriteMap指令。
      3. 更改倒数第二条规则以使用与上一条规则相同的RewriteCond
      4. &s=%{menumap:%2|0}添加到最后两条规则中。