6

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

2 Answers 2

14
  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

Sign up to request clarification or add additional context in comments.

5 Comments

There is one problem I have encountered, which is that if you enter an invalid url, it opens index.php many times inside one another. Any Thoughts on how to have an Error come up instead?
Anything that isn't a real link. x is a .php file that is read within index.php, so if I have example.com/docs and there isn't a docs.php, then index.php is opened within itself again and again.
Do you have some other code than I what I have in my answer here (like hiding .php extension)?
I believe there is on the server, but I don't have access to it. I have managed to create a workaround by including a check within index.php
This helped me stop bashing my head into the desk.
2

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) ""
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.