How can I create friendly URLs with .htaccess?
I'm having a hard time with .htaccess. I want to create friendly URLs for a site I'm working on...
Basically I want to convert this:
http://website.com/index.php?ctrl=pelicula&id=0221889
http://website.com/index.php?ctrl=pelicula&id=0160399&tab=posters
Into this:
http://website.com/pelicula/0221889/
http://website.com/pelicula/0221889/posters/
In case I need it later I would also want to know how to add the article title to the end of the URL like this (I'm using PHP):
http://website.com/pelicula/0221889/the-article-name/
http://website.com/pelicula/0221889/the-article-name/posters/
Note: Stackoverflow method is also good for me, for example the url of this question is:
http://stackoverflow.com/questions/3033407/htacces开发者_运维知识库-to-create-friendly-urls-help-needed
But you can put anything after the id and it will also work. like this:
http://stackoverflow.com/questions/3033407/just-anything-i-want
I have used some automatic web tools for creating the .htacces file, but its not working correctly. So I ask for your help.
I will also be glad if you can recommend .htacces best practices and recommendations..
EDIT: based on some answers I get here I put this:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/([^/]+)/([^/]+)/?([^/]*)/?$ index.php?ctrl=$1&id=$2&tab=$3 [QSA,L]
</IfModule>
But I get the default host 'page not found' error.
I also tried:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]+)/(\d+)/([^/]+)/?$ index.php?ctrl=$1&id=$2&tab=$3 [QSA,L]
RewriteRule ^([^/]+)/(\d+)/?$ index.php?ctrl=$1&id=$2 [QSA,L]
RewriteRule ^([^/]+)/?$ index.php?ctrl=$1 [QSA,L]
</IfModule>
This also does not work. It takes me to my default 404.php page.
mod_rewrite is enabled and working.
Help!
In the document root for http://website.com/
I'd put an htaccess
file like this:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
</IfModule>
Then in your PHP script you can manipulate the $_GET['url']
variable as you please:
$path_components = explode('/', $_GET['url']);
$ctrl=$path_components[0];
$id=$path_components[1];
$tab=$path_components[2];
Just tested this locally and it seems to do what you need:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/.]+)(?:/)?$ /index.php?ctrl=$1 [L]
RewriteRule ^([^/.]+)/([^/.]+)(?:/)?$ /index.php?ctrl=$1&id=$2 [L]
RewriteRule ^([^/.]+)/([^/.]+)/([^/.]+)(?:/.*)?$ /index.php?ctrl=$1&id=$2&tab=$3 [L]
</IfModule>
This is what it does:
- For a path like http://website.com/pelicula/, redirect to /index.php?ctrl=pelicula
- For a path like http://website.com/pelicula/0221889, redirect to /index.php?ctrl=pelicula&id=0221889
- For a path like http://website.com/pelicula/0221889/posters/, redirect to /index.php?ctrl=pelicula&tab=posters
- For a path like http://website.com/pelicula/0221889/posters/anything-can-go-here, redirect to /index.php?ctrl=pelicula&tab=posters and ignore the rest of the path.
These rewrites will work with or without a trailing slash - if you want them to work only without the slash, remove the (?:/)?
from the end of the first two rewrites. You can also use mod_rewrite to add or remove a trailing slash as required.
The first one assuming your .htaccess file is in the root:
RewriteRule ^([a-zA-Z]+)/([0-9]+)(/)?$ index.php?ctrl=$1&id=$2
The second:
RewriteRule ^([a-zA-Z]+)/([0-9]+)/([a-zA-Z]+)(/)?$ index.php?ctrl=$1&id=$2&tab=$3
or if it's always posters
rather than different tabs:
RewriteRule ^([a-zA-Z]+)/([0-9]+)/posters(/)?$ index.php?ctrl=$1&id=$2&tab=posters
I added the (/)?
which should mean the URI will work with or without trailing slash.
As for the other I'd probably always keep the article at the end so the rewrite or add another /value
so the rewrite knows the difference between the tab and article or exclude dashes from the regex.
To have this url :
http://website.com/pelicula/0221889/posters
rewritten to this:
http://website.com/index.php?ctrl=pelicula&id=0221889&tab=posters
I would do this:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/([^/]+)/([^/]+)/?([^/]*)/?$ index.php?ctrl=$1&id=$2&tab=$3 [QSA,L]
</IfModule>
You have to choose if you want to put the title after the id and do it all the time, because of the tab variable being in last position: you have to know if it's going to be number 3 or number 4. If you do this:
RewriteRule ^/([^/]+)/([^/]+)/?([^/]*)/?([^/]*)$ index.php?ctrl=$1&id=$2&tab=$4 [QSA,L]
the third parenthesis is not captured, and can therefore contain anything.
Hope that helps
Make sure you don't have any other .htaccess file higher up on the directory tree that's conflicting with your site's .htaccess.
I use this in my .htaccess
file
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* rewrite.php [L]
Basically if it doesn't exist as a file or a directory, use rewrite.php and let that take care of URL parsing etc. That is I believe the most basic way you can rewrite.
Also, check out the results of var_dump($_SERVER)
(somewhere you know works) to see if what you think is the topmost directory really IS the topmost directory, eg: you may be writiting to /var/www/domain/www/index.php
instead of /var/www/domain/index.php
Based on experience, I would recommend adjusting your URI scheme to make it easier to only apply the rule to URIs that you KNOW are re-written. For example
Convert this:
http://website.com/index.php?ctrl=pelicula&id=0221889
http://website.com/index.php?ctrl=pelicula&id=0160399&tab=posters
Into this (I have put the word "stuff", but this really ought to be something that describes what you are likely to find, i.e. "shop" or "library" or whatever this content is):
http://website.com/stuff/pelicula/0221889/
http://website.com/stuff/pelicula/0221889/posters/
To achieve this, you would put a .htaccess file in the top-level folder of your website that contains the following rules:
RewriteEngine on
RewriteRule ^stuff/([^/\.]+)/([^/\.]+)/([^/\.]+)/?$ index.php?ctrl=$1&id=$2&tab=$3 [L,NC,QSA]
RewriteRule ^stuff/([^/\.]+)/([^/\.]+)/?$ index.php?ctrl=$1&id=$2 [L,NC,QSA]
By having the "stuff" part of the address (renamed to something appropriate), you won't accidentally rewrite other assets such as images, CSS includes and JavaScript includes.
As a side note, you've mentioned:
This also does not work. It takes me to my default 404.php page.
Where is your 404 error redirection declared?
RewriteRule ^stuff/([^/.]+)/([^/.]+)/([^/.]+)/?$ index.php?ctrl=$1&id=$2&tab=$3 [L,NC,QSA] RewriteRule ^stuff/([^/.]+)/([^/.]+)/?$ index.php?ctrl=$1&id=$2 [L,NC,QSA]
精彩评论