views:

51

answers:

2

How could i use a RewriteRule accesing a variable?

If i have:

SetEnv MY_VAR (a|b|c)

RewriteRule ^%{ENV:MY_VAR}$ index.php?s=$1 [L,QSA]

RewriteRule ^%{ENV:MY_VAR}-some-one$ index.php?s=$1 [L,QSA]

I have these examples but doesn`t work.

Later edit

Ok Tim, thank you for the answer. Let say that i have:

RewriteRule ^(skoda|bmw|mercedes)-([0-9]+)-([0-9]+)-some-think$ index.php?a=$1 [L,QSA]

RewriteRule ^some-one-(skoda|bmw|mercedes)/pag-([0-9]+)$ index.php?a=$1 [L,QSA]

RewriteRule ^a-z-(skoda|bmw|mercedes)$ index.php?a=$1 [L,QSA]

(forget second part of RewriteRule) .. I don-t want to put everywhere (skoda|bmw|mercedes) this list. Is more quickly to make a variable then to use it in rule...

A: 

You can't do that, because mod_rewrite doesn't expand variables in the regular expression clauses.

You can only use variables in the input argument to a RewriteCond, and as the result argument to a RewriteRule. There's overhead in compiling the regular expressions (especially if you're forced to do it per-request as with .htaccess files), so if you allowed variable content in them, they'd have to be recompiled for every comparison to ensure accuracy at the cost of performance. It seems the solution therefore was to not let you do that.

What exactly did you want to do that for, anyway?

Tim Stone
see later edit.
oriceon
You can't just accept whatever is passed in and then have your script deal with the URL appropriately if it's incorrect? Also, does this list really change that frequently?
Tim Stone
Isn`t change frequently but i have about 100 lines in .htacces and almost all have some repeating stuff.
oriceon
Hm, the best advice I could give in that case would be to have a template `.htaccess` file that you could do a find+replace in when you needed to change the variables, then save a copy of that to use. That's an awfully long `.htaccess` file too; there's no way to condense some of your rules so you don't have as much to change? I can imagine changing it is quite annoying, it's just something `mod_rewrite` unfortunately can't fix for you in any useful way I'm afraid.
Tim Stone
A: 

I`ve received another answer on a mod_rewrite forum from jdMorgan:

Mod_rewrite cannot use a variable in a regex pattern. The .htaccess directives are not a scripting language...

I'd recommend:

RewriteCond $1<>$3 ^<>-([0-9]+)-([0-9]+)-some-think$ [OR]
RewriteCond $1<>$3 ^some-one-<>/pag-([0-9]+)$ [OR]
RewriteCond $1<>$3 ^a-z+-<>$
RewriteRule ^([^\-/]+[\-/])*(skoda|bmw|mercedes)([\-/].+)?$ index.php?a=$2 [QSA,L]

Here, the RewriteRule pattern is evaluated first (See Apache mod_rewrite documentation "Rule Processing").

If the pattern matches, then whatever comes before "(skoda|bmw|mercedes)" in the requested URL-path is placed into local variable "$1".

Whatever follows "(skoda|bmw|mercedes)" is placed into local variable $3.

The value of the requested URL-path matching "(skoda|bmw|mercedes)" is placed into $2.

Then each of the RewriteConds is processed to check that the format of the requested URL without the "(skoda|bmw|mercedes)" part is one of the formats to be accepted.

Note that the "<>" characters are used only as a separator to assist correct and unambiguous parsing, and have no special meaning as used here. They simply "take the place of" the variable-string that you do not want to include in each line. You can use any character or characters that you are sure will never appear in one of your URLs without first being URL-encoded. I prefer to use any of > or < or ~ myself.

Note also that the RewriteRule assumes that the "(skoda|bmw|mercedes)" substring will always be delimited by either a hyphen or a slash if any other substring precedes or follows it. I am referring to the two RewriteRule sub-patterns containing "[^-/]" ("NOT a hyphen or a slash") and "[-/]" ("Match a hyphen or a slash"). This greatly improves efficiency of regular-expressions pattern matching, so use this method if possible instead of using an ambiguous and inefficient sub-pattern like ".*" (Match anything, everything, or nothing").

oriceon