Forum Moderators: phranque
I'm in the process of converting my website to use nicer URLs. Some of them use long query strings, like this
domain.com/example.php?show=all&cat=category&sort=method&lang=english
I don't have a problem with rewriting this to example/all/category/method/english with (for example)
RewriteRule ^example/(.*)/(.*)/(.*)/(.*)/? /example.php?show=$1&cat=$2&sort=$3&lang=$4
The problem is, the URL can work just fine without some of these queries, but the new URL can't; example/category or anything that doesn't match the length in the rewrite rule displays 404.
I realize I can do this with writing additional rules for every possible URL length, but is there a shorter and simpler way?
[edited by: Gouran at 3:17 pm (utc) on Jan. 8, 2008]
No, not really. You'll need to handle it on a case-by-case basis.
Also, beware of potential trouble such as that described in this thread [webmasterworld.com]. Note also the use of efficient patterns in the code in that thread.
Jim
The &lang=english is basically unnecessary because the default is English and it's only required for the other languages to show up. The reason I'm mentioning this is I want to push the /language/ to the beginning of the URL instead of tacking it on the end, but also not show it at all if I want English. Like this:
domain.com/news/ID is in english
domain.com/language1/news/ID displays some other language
The only way of doing this I can think of is
RewriteRule ^(language1¦language2¦etc)/news/(.*)/? /news.php?id=$2&lang=$1
RewriteRule ^news/(.*)/? /news.php?id=$1
Doesn't sound like too much until you get to the long optional URLs
RewriteRule ^example/(.*)/(.*)/(.*)/(.*)/? /example.php?show=$1&cat=$2&sort=$3&lang=$4
RewriteRule ^example/(.*)/(.*)/(.*)/? /example.php?show=$1&cat=$2&sort=$3
... and so on
and then doubling each and every one adding (language) variables at the beginning. I don't even know if it can complicate things if you have too many lines in .htaccess.
1) If this can be done without so many lines, but is beyond my obvious beginner's level, please say so :). I will then just tack on /language at the end of the URL. But it would be neat to have it this way.
2)The efficient patterns you mention, I suppose you're referring to (.*) I used? I'm actually using ([0-9]+) and similar, is it better to use ([^/]+)?
RewriteRule [b]^((l[/b]anguage1Šlanguage2Šetc)[b]/)?n[/b]ews/([^/]+)/?$ /news.php?i[b]d=$3&lang=$2[/b] [L]
RewriteRule ^(([a-z]{2})/)?news/([^/]+)/?$ /news.php?id=$2&lang=$1 [L]
That depends. Make the pattern as specific as possible. Just avoid the "(.*)xx(.*)xx(.*)" type of patterns, because they can be extremely inefficient to process.
Two ".*" subpatterns in one pattern is not so bad, but four or five or more can bring a busy server to its knees -- The parsing time grows proportionately to the factorial of the number of subpatterns and the length of the URL-path being matched. The parser has to try dozens, hundreds, thousands or even hundreds of thousands of "trials" and then find the "best fit" to your pattern. By contrast, a specific pattern can be evaluated in a single left-to-right pass.
Jim
I was trying something similar for the long URLs -- to put a? before / to try and make it optional -- but it wasn't working. Didn't think of wrapping it up with additional ().
For the (.*) issue; I'll keep that in mind, though I wasn't really using it. It was just easier copy pasting that while I was writing the example.