Advertise here: Contact FM.


Regex woes.
June 10, 2008 5:27 PM   RSS feed for this thread Subscribe

Not quite getting how mod_rewrite regex works when flatting urls with multiple variables.

Hello hello,

Ok, so I'm working on another website but I have run into what I'm sure is a pretty basic problem that I can't seem to wrap my head around. I use mod_rewrite pretty frequently to flatten the most basic types of dynamic urls, those with only one variable. But now I need to figure out how to configure my htaccess to handle urls that always have one variable, but sometimes also have 2-3.

Now if I knew the same number of variables would be present all the time I think I could handle it, but when there is a variable number of variables I just can't seem to figure out what I'm doing.

Here is an example of what I do know how to do. Let's say I want to change the url:

http://mywebsite.com/profile/jeremy/

into:

http://mywebsite.com/profile.php?name=jeremy

I'd use:

ReWriteRule ^profile/([A-Za-z]+)/$ /profile.php?name=$1

but if sometimes I also add extra variables like so:

http://mywebsite.com/profile/jeremy/action/sort/order/desc/

into:

http://mywebsite.com/profile.php?name=jeremy&action=sort&order=desc

Then I just can't seem to wrap my head around it. Especially if depending on circumstances I might have urls like so where the 2nd variable in the previous example is missing, but the third is still round:

http://mywebsite.com/profile/jeremy/order/desc/

I've Googled around but it seems most websites toughing on the subject are either too simple (and just give examples with single variables) or are too complicated and assume I already have abase level of regex knowledge which I sadly lack.

So would any kindly Mefite want to give me a walk through on what exactly I should be trying to do (and most importantly why, so that I can avoid just rote copy/pasting and instead be able to solve these kind of problems myself in the future =)

Thanks much!
Jeremy
posted by Jezztek to computers & internet (5 comments total) 5 users marked this as a favorite
Consider using the [QSA] flag, which appends existing get queries to the rewrite to take care of some of the query strings. (See here for a more elaborate explanation). I do not feel like ordering/sorting info needs to be in a URL -- that's fine for a query string. As for actions, simply have two rules (I believe you need the [L] flag for this), one which rewrites strings with actions, one which does not:

ReWriteRule ^profile/([A-Za-z]+)/([A-Za-z]+)/?$ /profile.php?name=$1&action=$2 [QSA,L]
ReWriteRule ^profile/([A-Za-z]+)/?$ /profile.php?name=$1 [QSA,L]


I'm sure you could do it in one, but this seems much more clear to me. Readability and maintainability is typically more important than (presumed) optimization. If you're doing any more rewriting than one or two vars, consider tossing the entire string into a get var that is processed by a server-side script.

It also looks like you're trying to set both query KEYS and VALUES in your urls -- ie, you want to do something like :

ReWriteRule ^profile/([A-Za-z]+)/([A-Za-z]+)/([A-Za-z]+)?$ /profile.php?name=$1&$2=$3 [QSA,L]


In theory, you can do this, but I think it's going to be super confusing, and I've personally never seen an app work this way -- it forces you to have to handle a crapload of 404s that would otherwise be routed by apache.

Something else to keep in mind: are you limiting user names to just letters? Your rewrite will fail for people using underscores, spaces, or numbers in their names.
posted by fishfucker at 6:10 PM on June 10


Er, to better explain my first example, your URL might look like :


/profile/jeremy/sort?order=DESC


i feel like if you're sending an 'order' get var, it's pretty obvious you're wanting to sort, so really, the sort action is redundant, but maybe you'll have a diff action, like


/profile/jeremy/blogs/?sort=date&order=DESC


Note how I moved the sort field and order into the get vars -- I really think that's the most appropriate place for it, since you're *modding* a default. IMO, URLs should always go to a DEFAULT VIEW, while a MOD of that DEFAULT VIEW should appear as a GET var. It just seems more consistent. That way I know I can get to a default view by removing all get vars.
posted by fishfucker at 6:14 PM on June 10


Seconding fishfucker heartily - the reason you're having trouble doing this is that it's really a weird thing to do. Things like sort and order really do belong in the query string, even if you're otherwise beautifying your URLs.

Now, that said, the following rules do what you want, modulo the ^/profile/ part which you may have to change:

RewriteRule ^/profile/([^/]+)/([^/]+)/([^/]+)/?(.*) /profile/$1/$4?$2=$3 [N,QSA]
RewriteRule ^/profile/([^/]+)/$ /profile.php?name=$1 [QSA]


The first rule matches /profile/ then at least three slash-separated chunks of characters (I didn't preserve your letters-only semantics here.) It then redirects to /profile/ again, preserving the first chunk (which is the name in your example) and extracting the next two, turning them into a piece of the query string ($2=$3). $4 is a general "rest of the string", since we need to preserve pieces of the path we haven't turned into query string chunks yet. The N flag means to run the ruleset again with the changed URL, and QSA means "keep the old query string and just add on what I've added here". The N flag provides the magic here, since we run this rule over and over again until we run out of path chunks to convert.

The second rule matches when we've run out of slash-separated chunks - we need a special case because you're using /profile/jeremy/, not /profile/name/jeremy/. Again, we preserve the old query string and simply add the name=$1 to capture the name, which you're familiar with.

The rules above aren't polished; for instance, they fail if you access a URL like /profile/jeremy/sort/desc/extra/. That's okay, because honestly I don't think you're going to want to go through with this. It's a testament to mod_rewrite's flexibility that you can do it pretty easily, but you really, really don't want to go down that road.
posted by pocams at 6:28 PM on June 10 [2 favorites]


wow, pocams, i am in awe. This is the first time I've ever seen a recursive mod_rewrite rule.
posted by fishfucker at 6:41 PM on June 10


Wow, thanks much guys, I wasn't even aware of the QSA flag. Which I suppose is why I couldn't find good info on doing what I was trying to do =)
posted by Jezztek at 7:27 PM on June 10


« Older While traveling in Italy, I ha...   |   Give me Bobby Fischer Teaches ... Newer »

You are not logged in, either login or create an account to post comments



Related Questions
Help me remember this Free Custom Ringtone site! January 26, 2008
Formatting hyperlinks August 8, 2007
How does one make an offer on a domain name? May 1, 2007
Highlight and click? August 10, 2006
.htaccess question. I want to turn all the... September 24, 2004