开发者

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]

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜