I have a site written in php which creates 'pretty' urls for each item (on category and search pages) like this,
mysite.com/category/slug-for-item-one/1
mysite.com/category/slug-for-item-two/2
The /category/ and /slug/ is dependent upon the numeric id of the item
I have mod_rewrite serve the actual content from urls like this:
mysite.com/view-item.php?id=1
mysite.com/view-item.php?id=2
The content for each item is retrieved using just the items id.
Here's my htaccess:
RewriteEngine on
RewriteRule ^([^/\.]+)/?$ view-item.php?id=$1 [L]
RewriteRule ^([^/\.]+)/([^/\.]+)/?$ view-item.php?pid=$2 [L]
RewriteRule ^([^/\.]+)/([^/\.]+)/([^/\.]+)/?$ view-item.php?id=$3 [L]
Everythings ok so far but, if someone lands on on a url like,
mysite.com/1
mysite.com/catey/slug-for-item-one/1
or
mysite.com/category/slug-item-one/1
the content is still served, but how can I automatically reset or redirect to the canonical version of the url, to:
mysite.com/category/slug-for-item-one/1
I've searched SO and google extensively for an answer, but no luck. I've only used mod_rewrite for simple redirects such as from without www. to with www. and my understanding is tentative thus I'm struggling to understand how to proceed at the moment.
Can anyone point me in the right direction?
Thank you everyone for your help. Much appreciated. I'm working on an implementation of Jon Lin's answer as I'm more familiar with using php/mysql databases and understand how and why it should work. I aim to be done by Friday and will update this page when finished. Many thanks, Karl.
* UPDATE * I have implemented Jon Lin's answer and now my 'pretty' urls, when mistyped are now redirected to the correct or 'canonical' url just as on SO. Thank you Jon and everyone who contributed!
I think you are going to need two sets of rewrite rules to accomplish this.
The first set of rules would be used to send 301 redirects to the client to ensure they are referencing the canonical URLs:
Then a second set of rules that use passthroughs [PT] to serve up the content:
Or something along those lines...
This is probably something you want to implement in your
view-item.php
instead of trying to use mod_rewrite. When you are generating the links internally within your content, you can use the ID's to lookup categories and slugs. This would be how you normally go about generating one of the pretty SEO friendly links.You first need pass the category and slug into the request. Something along the lines of:
At the top of your view-item.php, simply check if the
cat
andslug
parameters exist, compare them to the actual category and slug when you do the lookup for theid
. If one of them doesn't match (or is missing, if you want), then redirect the browser to the correct link with the correct category and slug using theheader()
function:After they get redirected, the process repeats itself, but this time, view-item.php sees the correct category and slug so the page gets served like normal.
Easy as pie:
This means: if the request does look like
category/slug-for-item-two/2
and the first match is not the wordcategory
(whatever it is) then force the redirect tocategory/slug-for-item-two/2
Please tell me if it works
Update (after your comment):
Here's what should work:
Create 2 map files (see mod_rewrite.html#rewritemap to learn how to do).
Create a mapfile where you put all the categories you need:
In the mapfile create simple entries like:
Now do another file with the opposite:
In the mapfile create simple entries like:
Then here you go for the hard part:
This way everything is dynamic but it's (much) longer and (a little bit) more complex.
Olivier