Question

I finally figured out a good/easy way to make clean URLs with regex on my site in this format below, however it will require a very large .htaccess file, I know from the post on here that it is supposed to not be to bad on performance to use mod_rewrite but I have never really seen it used where the way I am, with a seperate entry for almost every page of my site.

Below is an example of an entry, there is 2 entries for 1 page, the first entry re-writes

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

It works great but if the user is not on the first page then there is another thing added to the URL for paging and I had to write another entry to rewrite when this happens, is this the correct way or should these be combined somehow?

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

The second one would do this

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

Was it helpful?

Solution

It depends what you think is more readable, but here's how you could do it with a single rule:

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

(Edited to be more faithful to treatment of trailing slash in original question. Was: RewriteRule ^users/online/friends/((\d+)/*)?$ ./index.php?p=users.online.friends&s=8&page=$2)

Here I've just put "(...)?" around the final part of the url to make it an optional match, and changed the backreference to $2.

Of course, this actually rewrites http://www.domain.com/users/online/friends/ as:

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

So your PHP code would have to check whether the page parameter is non-empty.

OTHER TIPS

Yes, that's fine. I guess they could be combined into a single rule but there's not really any need.

You might consider leaving page as part of the URL so instead of:

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

just have:

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

and then have one rule something like:

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

to append the query string

Edit: There are a couple of ways of reducing the number of rewrite rules you have.

Firstly, use wildcards in the search terms, like:

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

will reduce quite a number of rules.

Secondly, if you're passing everything through /index.php just consider delegating all requests there:

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

That rule uses a third technique: instead of passing the path information via a query string parameter, pass it via the extra path info. That can be accessed via $_SERVER['PATH_INFO'].

That being said, lots of rules isn't necessarily bad. At least it's explicit about all your actions. The thing you have to watch out for is creating a maintenance nightmare however.

# 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]

This would rewrite the URL in several steps:

  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

An easier method would be the following, but would require you to change your scripts:

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

It would do everything in one step, with a little difference:

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

Adding the s=8 query argument would require more work:

  1. Creating a text-file with the menu numbers for each page.
  2. Adding a RewriteMap directive.
  3. Changing the second-last rule to use the same RewriteCond as the last rule has.
  4. Adding &s=%{menumap:%2|0} to the last two rules.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top