MassivePenguin
MassivePenguin

Reputation: 3511

.htaccess - redirecting several pages

I've been trying to wrap my head around .htaccess for most of the weekend, but I keep stumbling; I can get the server to work with one set of rules, but no more than one at a time.

My application is made up of several pages:

Each of these pages is a php file in the document root (index.php, detail.php, collection.php, related php).

What I would like to achieve:

This is what my .htaccess file looks like at present, after much fiddling:

<IfModule mod_rewrite.c>  
    RewriteEngine on
    RewriteBase /
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ index.php?s=$1 [L]
</IfModule>

This allows the homepage to pull in the correct content, and I'm sure it's not too far off allowing any page to do the same, but I can't quite fathom it.

Can anyone help?

Upvotes: 0

Views: 123

Answers (1)

Mike Rock&#233;tt
Mike Rock&#233;tt

Reputation: 9007

RewriteEngine On
RewriteBase /

# Specifics
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} ^/([^/]+)/(.+)/?$
RewriteCond %{DOCUMENT_ROOT}/%1.php -f
RewriteRule ^ %1.php?s=%2 [L]

# EDIT 1: This will also check for root pages. See notes below
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ([^/]+)/ $1 [R=301,L]
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule (.+) $1.php [L,QSA]

# Everything else
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?s=$1 [L]

Explanation:

  1. First, we check that the full REQUEST_FILENAME does not exist.
  2. Then, we check to see that the format is as follows: /<something-without-slash>/<everything else> (with an optional trailing slash).
  3. We then check to see if our first condition-capture exists as a PHP file in the document root. For example, if we request foo/bar, it would check to see if /foo.php exists.
  4. Then we simply route the request to the correct file, with the correct query string.

So, in your case, when you request detail/item-name, the server would actually be looking at detail.php?s=item-name to provide you with a response.

Note: If it does not exist, the request will simply send the request to index.php.

Edit: Have added detection for root pages. Note, however, that I cannot get it to leave a slash for this kind of detection as it automatically amends .php to the empty s query paramater. Not sure why... This is why when it reaches this stage, it will remove any trailing slashes. This is also good for SEO ratings/rankings as it is seen as one page, and not two duplicates.

Upvotes: 1

Related Questions