Forum Moderators: phranque
I am trying to get my head around mod rewrite at the moment. I have the following url:
http://www.example.com/index.php?market=$1&product=&2&subcat=$3
All variables are optional so a url could be either of the following:
index.php?market=$1&product=&2
index.php?market=$1
index.php?market=$1&product=&2&subcat=$3
However using the mod reqrite code I have at the moment, it will only redirect when all three variables are present:
RewriteEngine on
RewriteRule ^(.*)/(.*)/(.*)/$ index.php?m=$1&p=$2&s=$3 [L]
RewriteCond %{REQUEST_URI} ^/[^\.]+[^/]$
RewriteRule ^(.*)$ [%{HTTP_HOST}...] [R=301,L]
Could anyone point me in the right direction?
Many thanks, Will.
You will either need to use a separate rule for each possible combination of present/not-present path-values, or us a single rewriterule with a specific RewriteCond for each possible combination of present/not-present path-values.
Because your URL format appears to be 'fixed-order,' you should be able to do this using four rules:
RewriteEngine on
#
# Externally redirect to add missing trailing slash if URL path does not contain a period or end with a slash
RewriteCond $1 ^[^\.]+[^/]$
RewriteRule (.*) http://%{HTTP_HOST}/$1/ [R=301,L]
#
# Internally rewrite SEO-friendly URLs to script
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/$ index.php?m=$1&p=$2&s=$3 [L]
RewriteRule ^([^/]+)/([^/]+)/$ index.php?m=$1&p=$2 [L]
RewriteRule ^([^/]+)/$ index.php?m=$1 [L]
Be aware that the rules above are potentially dangerous: You will not be able to use any 'real' subdirectories whatsoever on this server with these rules in place, because all will be rewritten to index.php. This may be a problem if, for example, your script does not support the Web-standard privacy-policy implementation, which requires a file named /p3p.xml in a subdirectory named /w3c. You may need to add exclusions to these rules if you have any physically-existing subdirectories.
Note as well that external redirects must be done before internal rewrites; Otherwise, a later redirect would expose and earlier rewrite to the client, destroying any advantage of linking to 'SEO-friendly' URLs. In general, place external redirects first in order from most-specific to least-specific, followed by internal rewrites, again from most-specific to least specific.
Jim
The code works as described but I can't continue if I can not directly link to folders and files though!
I presume I could always create a sub directory in my root called products and then create a .htaccess with the rewrite rules within that and then I could link to files in folders in the root directory?
Thanks again,
Will.
You may need to add exclusions to these rules if you have any physically-existing subdirectories.
So that leaves only directory index URLs, whether producing actual directory listings or accessing "index.xyz" in the directory (through the action of the DirectoryIndex directive) that need to be provided for.
If that's not clear, consider your 'home page'. It usually has a URL of example.com/. DirectoryIndex is most often used to rewrite that to example.com/index.html or example.com/index.php, just for example.
Now consider example.com/subdir/. This might produce a directory listing of all files in example.com/subdir, or if DirectoryIndex is applied, and the file exists, then the server would serve example.com/subdir/index.html or example.com/subdir/index.php.
In the second case (with a request for /subdir), the last rule I posted will rewrite this request to index.php?m=subdir unless you take steps to prevent this. You can do so in several ways, each with advantages and disadvantages. The trade-off is almost always a server slow-down versus your convenience.
for example, you could use
RewriteCond $1 !^subdir
RewriteRule ^([^/]+)/$ index.php?m=$1 [L]
On the other hand, you might use
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/$ index.php?m=$1 [L]
The advantage, though, is that you need not maintain a list (in the RewriteCond) of all existing subdirectories; If they are 'real' subdirectories, the rule won't rewrite requests for them. So, it puts a lot more load on the server compared to the first method above, but is much easier on you.
Only you can choose what's right for your site.
Jim
How well would this work? :
If I placed an .htaccess file with the same rewrite conditions and rules in a subdirectory /products/ for example and have a script in there to process the variables and then I can always link to ../anotherdirectory/ from there?
Thanks, Will.
There is no need to reproduce the same code in your subdirectories. See "RewriteOptions inherit"
Suggestion: Get the code working in your top-level .htaccess file, then re-assess and move the code to a subdirectory if necessary. Because mod_rewrite changes the URL-to-filename 'map' of your server in rather dramatic ways, it is best to be cautious and proceed in small steps, testing thoroughly at each step, rather than to install a large and/or complex set of rules and then try to test it all at once.
Jim