shorten/compress mod_rewrite rules - .htaccess

amongst my rules i have..
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/\.]+)/([^/\.]+)/([^/\.]+)/([^/\.]+)/?$ index.php?page=$1&submenu=$2&info=$3&id=$4 [QSA,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/\.]+)/([^/\.]+)/([^/\.]+)/?$ index.php?page=$1&submenu=$2&info=$3 [QSA,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/\.]+)/([^/\.]+)/?$ index.php?page=$1&submenu=$2 [QSA,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/\.]+)/?$ index.php?page=$1 [QSA,L]
Which seems a little bulky to me and repeats a lot of stuff, any ideas on how i can shorten it?
Can i set "global" conditions?
Can i have one rule like this that captures all the ones below it (i dont care if it sends through empty varibles)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule **clever stuff here** index.php?page=$1&submenu=$2&info=$3&id=$4 [QSA,L]
So it would capture
domain.com/a/b/c/d
and
domain.com/a/b/c
and
domain.com/a/b
and
domain.com/a
Answers, Thoughts, Musings, and Existential Arguments all appreciated...

You can pretty easily remove the conditions if you check for the inverse and let it pass through the rewrite engine. Then anything afterwards you know isn't an existing file or directory:
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^([^/\.]+)/([^/\.]+)/([^/\.]+)/([^/\.]+)/?$ index.php?page=$1&submenu=$2&info=$3&id=$4 [QSA,L]
RewriteRule ^([^/\.]+)/([^/\.]+)/([^/\.]+)/?$ index.php?page=$1&submenu=$2&info=$3 [QSA,L]
RewriteRule ^([^/\.]+)/([^/\.]+)/?$ index.php?page=$1&submenu=$2 [QSA,L]
RewriteRule ^([^/\.]+)/?$ index.php?page=$1 [QSA,L]
It's not a fancy multiple-look-ahead regex that does it all in one line, but it does make it easier to read.
EDIT:
Well, like I said, you do it with multiple look-aheads, something like:
RewriteRule ^(?:([^/.]+)|)(?:/([^/.]+)|)(?:/([^/.]+)|)(?:/([^/.]+)|) index.php?page=$1&submenu=$2&info=$3&id=$4 [QSA,L]
But it's harder to read, and more likely to do something unexpected if you change something. Additionally, whereas having explicit 4 different mappings, you don't get blank query string params like you do with look-aheads. Whether the last (?:/([^/.]+)|) is there or not, you will still get an id param (just blank).

Related

Mod Rewrite, convert subdirectory to query string?

I'm trying to convert subdirectories to a search query. So basically:
example.com/pizza
would be converted to:
example.com/?s=pizza
I have a basic knowledge of htaccess and I have done similar things before, however this time I cannot make it work. This is the problem:
This works:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.*)$ /results/?s=$1 [L,QSA]
However when I point the rewrite target to the root the user is redirected to "example.com" without the query string.
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(.*)$ /?s=$1 [L,QSA]
How can I rewrite "example.com/pizza" to "example.com/?s=pizza" ?
You may try this:
Options +FollowSymlinks
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^(?:.*)?/([^/]+)/? [NC]
RewriteRule .* /?s=%1 [L]
Maps silently:
http://example.com/any/number/of/folders/parameter with or without trailing slash.
To:
http://example.com/?s=parameter
All strings are assumed to be variable.
For permanent and visible redirection, replace [L] with [R=301,L].

htaccess - rewritecond to check for slash

I have a rewriterule on my site thats like this:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ open.php?url=$1 [L]
(There is a lot above it but this is the last rule)
It works very nicely.
What I want to achieve, however, is that if the url is as follows:
http://site.com/first/second
Then I want to redirect to
open.php?url=$1&open=$2
The problem is that I want to have both of them at the same time so that site.com/foo works as well as site.com/foo/bar . I also want to avoid having a trailing slash there all the time ergo both of the rules at the same time.
If there a way to check for trailing slashes with a rewritecond of some sort
any help is appreciated :)
SOLVED
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/(.*)/(.*)$
RewriteRule ^(.*)$ open.php?url=$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} /(.*)/(.*)
RewriteRule ^(.*)/(.*)$ open.php?url=$1&open=$2 [L]
All I had to add was a RewriteCond %{REQUEST_URI} !^/(.*)/(.*)$ on the first rule!

.htaccess - Querystring without index.php

I want my url's to look like this: "http://www.example.com/start",
and not like this: "http://www.example.com/index.php/start".
That works fine with this code in my .htaccess:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?/$1
On one page i have to work with GET-Parameters, the url should look like this:
"http://www.example.com/artists/picasso",
and not like this:
"http://www.example.com/index.php/artists?artist=picasso"
That's also possible with the following code:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /index.php?/$1
RewriteRule ^artists/(.*)$ /index.php/artists?artist=$1 [L]
Now, the problem with this solution is, that all other url's now have to end with a slash.
So it has to look like this: "http://www.example.com/start/",
and not like this: "http://www.example.com/start"
Thanks for your help !
Try changing your rules to:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !artists/
RewriteRule ^(.*?)/?$ /index.php?/$1
RewriteRule ^artists/(.*)$ /index.php/artists?artist=$1 [L]
Mainly, you have a /$ at the end of your pattern: RewriteRule ^(.*)/$ /index.php?/$1 which means it has to end with a slash in order to match the pattern. Changing it to (.*?)/?$ makes it optional.

.htaccess mod_rewrite and Query Strings

In my .htaccess file I've got a rule that strips the .php:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]+)/$ $1.php
RewriteRule ^([^/]+)/([^/]+)/$ /$1/$2.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/)$
RewriteRule (.*)$ /$1/ [R=301,L]
So, /mydomain.com/page.php becomes /mydomain.com/page/ - Which works fine.
Now I'm trying to achieve something similar with query strings, where:
/mydomain.com/page.php?variable=value becomes /mydomain/page/value/
I've tried numerous methods and the best I can get is /mydomain/page/?variable=value
Your second rule is
RewriteRule ^([^/]+)/([^/]+)/$ /$1/$2.php
You can change this to rewrite to a query param like this:
RewriteRule ^([^/]+)/([^/]+)/$ /$1.php?variable=$2

url construction htaccess

Lets say I have a link to one of my page that looks like: mysite.com/48YSWD96, I need it to look like: mysite.com/?d=48YSWD96. How do I achieve this? Can I achieve this by modifying my htaccess file? which currently looks like this...
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^([^/]+)/$ $1.php
RewriteRule ^([^/]+)/([^/]+)/$ /$1/$2.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/)$
RewriteRule (.*)$ /$1/ [R=301,L]
RewriteBase /
It looks like you just need to append this to the end:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([A-Za-z0-9]+)$ /?id=$1 [L]
For it to work the other way around:
RewriteCond %{QUERY_STRING} (^|&)id=([A-Za-z0-9]+)($|&)
RewriteRule ^$ /%1 [L]
This will take a request for mysite.com/?d=48YSWD96 and change the URI to /48YSWD96. Essentially, whatever the id equals in the query string.

Resources