11

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!

Undo
  • 25,519
  • 37
  • 106
  • 129
Jonathan
  • 8,676
  • 20
  • 71
  • 101
  • http://stackoverflow.com/questions/2569725/getting-two-variables-in-the-url-with-htaccess/2569734#2569734 http://stackoverflow.com/questions/2088804/htaccess-confusing-clean-urls/2088854#2088854 http://stackoverflow.com/questions/2549408/needs-some-help-with-an-apache-mod-rewrite-issue/2549688#2549688 ... – Richard JP Le Guen Jun 13 '10 at 18:44
  • 1
    To see what your URLs are being rewritten to, try echoing $_GET at the top of index.php or using the rewrite log to debug. http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html#rewritelog – cam8001 Jun 17 '10 at 23:26
  • Are you ''really'' sure that rewriting is working properly? I had the same problems once with badly configured apache config files. http://www.webune.com/forums/how-to-test-check-if-mod-rewrite-is-enabled-t40.html really helped me – DrColossos Jun 22 '10 at 08:17

7 Answers7

7

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];
Richard JP Le Guen
  • 28,364
  • 7
  • 89
  • 119
  • I need to change all the web application to use this? I mean, I need to change all the $_GET in every single page? – Jonathan Jun 13 '10 at 19:04
  • 1
    @Jonathan: No, that's the whole point of it! You'll only have that code in the index.php page. Then index.php can decide what to do and `include` the needed page(s) depending on the $_GET variables – nico Jun 13 '10 at 21:24
  • This is called the Front Controller Pattern and is IMHO the way to go. – Sergiu Paraschiv Aug 27 '13 at 18:20
7

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:

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.

cam8001
  • 1,581
  • 1
  • 11
  • 22
  • Its not working on my web host. I get this error: Internal Server Error. The server encountered an internal error or misconfiguration and was unable to complete your request. Any idea? – Jonathan Jun 18 '10 at 12:31
  • Try removing the slash from in front of index.php on all of the rewrite rules. – cam8001 Jun 18 '10 at 20:19
  • I removed the slashes, same error. I think it might be a syntax error because when I tried the code provided by 'jfoucher' I don't get this problem... – Jonathan Jun 18 '10 at 21:40
  • Do you have access to the server logs? Can you see what is happening in the rewrite log? – cam8001 Jun 20 '10 at 10:47
  • I have no access to serlver logs, please read my other question http://stackoverflow.com/questions/3076122/php-routing-for-friendly-urls-help – Jonathan Jun 20 '10 at 12:38
0

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.

0

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.

desertnaut
  • 57,590
  • 26
  • 140
  • 166
jfoucher
  • 2,251
  • 2
  • 21
  • 29
0

Make sure you don't have any other .htaccess file higher up on the directory tree that's conflicting with your site's .htaccess.

0

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

Kristoffer Sall-Storgaard
  • 10,576
  • 5
  • 36
  • 46
0

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.

desertnaut
  • 57,590
  • 26
  • 140
  • 166
Fenton
  • 241,084
  • 71
  • 387
  • 401