Razattax
Razattax

Reputation: 163

htaccess multiple rewrite rules for different GET variables

I am trying to use htaccess Rewrite Rules to map multiple GET variables, but not all the variables are required. I have ordered the variables so that x is always required, if y is set, then z must be set, etc. So I need the mappings to look like this:

example.com/section/topic/sub

to map to

example.com/?x=section&z=topic&y=sub

However the following code causes Internal Error, but if I only have one Rewrite Rule, it works.

Options +FollowSymLinks
Options -indexes
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI}  ([^/]+)/?   [NC]
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/([^/]+)$  ?x=$1&z=$2&y=$3&r=$4    [NC,L]
RewriteRule ^([^/]+)/([^/]+)/([^/]+)$  ?x=$1&z=$2&y=$3    [NC,L]
RewriteRule ^([^/]+)/([^/]+)$  ?x=$1&z=$2    [NC,L]
RewriteRule ^([^/]+)$  ?x=$1    [NC,L]

</IfModule>

I also need to ensure the url can have a trailing /, but does not require it.

As you can probably tell, I am new to htaccess.

Thank You

Upvotes: 6

Views: 11141

Answers (2)

Steven
Steven

Reputation: 6148

It seems like you're going through a lot of trouble to do something that can be achieved in just one rule:

RewriteRule ^(.*)/*(.*)/*(.*)/*(.*)/*$ index.php?a=$1&b=$2&c=$3&d=$4

This will always return something like the following in PHP:

//var_dump($_GET);

array(4) {
  ["a"]=>
  string(#) "VALUE"
  ["b"]=>
  string(#) "VALUE"
  ["c"]=>
  string(#) "VALUE"
  ["d"]=>
  string(#) "VALUE"
}

Where the VALUE will either be empty if not set in the URL or the value if it is set.

N.B. You may also need to add the conditions that it is not an actual file/directory; depending on your site structure.

Example

Given:

http://example.com/section/topic/sub

The URL it's transformed to will be:

http://example.com/index.php?a=section&b=topic&c=sub&d=

Which will show up in PHP as:

//var_dump($_GET);

array(4) {
  ["a"]=>
  string(7) "section"
  ["b"]=>
  string(5) "topic"
  ["c"]=>
  string(3) "sub"
  ["d"]=>
  string(0) ""
}

Upvotes: 2

anubhava
anubhava

Reputation: 786289

  1. Don't know what RewriteCond %{REQUEST_URI} ([^/]+)/? is doing.
  2. Make trailing slash optional by using /?$
  3. Check for files/directories once at the top and skip applying the rules form them.

You can have your rules like this in DOCUMENT_ROOT/.htaccess:

Options +FollowSymLinks -indexes
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /

## If the request is for a valid directory
RewriteCond %{REQUEST_FILENAME} -d [OR]
## If the request is for a valid file
RewriteCond %{REQUEST_FILENAME} -f [OR]
## If the request is for a valid link
RewriteCond %{REQUEST_FILENAME} -l
## don't do anything
RewriteRule ^ - [L]


RewriteRule ^([^/]+)/([^/]+)/([^/]+)/([^/]+)/?$ ?x=$1&z=$2&y=$3&r=$4 [L,QSA]

RewriteRule ^([^/]+)/([^/]+)/([^/]+)/?$ ?x=$1&z=$2&y=$3 [L,QSA]

RewriteRule ^([^/]+)/([^/]+)/?$ ?x=$1&z=$2 [L,QSA]

RewriteRule ^([^/]+)/?$ ?x=$1 [L,QSA]

</IfModule>

Reference: Apache mod_rewrite Introduction

Upvotes: 14

Related Questions