mod_rewrite

I’m building a profile page, to access a profile of a certain you go to:

example.com/profile.php?id=[user_id]

e.g if a user has an id of 6

example.com/profile.php?id=6

each id of a member has a username associated with it in the database. I want to create this for each user:

example.com/john/

which will actually be this

example.com/profile.php?id=6

how do i do a rewriterule to accomplish this?

You can’t create a RewriteRule for this, since Apache doesn’t know that john has id 6.

You can either create a RewriteRule that will just pass everything to profile.php and let php figure out what it’s supposed to do using the path info (/john/), or use a RewriteMap.
Note that you can only use a RewriteMap if you have access to the main server config (httpd.conf), so this won’t work if you’re on a shared host (unless the host is very flexible).

mod_rewrite is a module of Apache and it does not directly deal with MySQL (or any) database. So it is not possible to have username instead of id from within the rewrite rule itself. So you have to pas the username to the PHP file/script page then find the id of the username (possibly on top of the script page). And the rewrite rule will look like this in your .htaccess file:


RewriteEngine On
^/(.*)/?$ /profile.php?username=$1

And in your PHP, you can get it:


$username = $_GET['username'];
// now you can get user's id by querying in the database.

More details for the examples of rewrite rules, see:

I understand.
Assuming I modified the code and made the request like this:

example.php/profile?id=john

What would the rewrite rule be?

Then it would be


RewriteRule ^(.*)/$ /profile.php?id=$1

Hi, im getting a 404

My files are all in a directory called /!

But i want it to be example.com/john
not
example.com/!/john

what am I doing wrong?

RewriteBase /!/

RewriteRule ^(.*)/$ /myprofile.php?id=$1

Where is myprofile.php ? Is it in / or in /!

I’d advice removing the RewriteBase and use the /!/ on every rule that needs it, and don’t put it on others, it’s just cleaner that way. Plus, RewriteBase usually causes more problems than it solves.

ok i will remove rewritebase.

myprofile.php is located in /!/

Well, then obviously the rule changes to


RewriteRule ^(.*)/$ /!/myprofile.php?id=$1

:slight_smile:

@Raju - incorrect. Rémon’s already mentioned that the RewriteMap (program type) can access a database, flat file, anything on the server but you MUST have access to the server or virtual host configuration file as any error can bring down Apache.

@Rémon - you KNOW better than to use (.) (without the trailing /) without providing a warning that it’s the most often abused (and greatest cause of problems) by/for newbies! Your version will work (the op’s /? won’t … without looping) but it’s dangerously close to (.) which newbies know and love despite not understanding the responsibility that comes with the power of the :kaioken: EVERYTHING :kaioken: atom!

Regards,

DK

So what should I be using? the given line of code does not seem to be working.

UPDATE:

This works:
http://www.example.com/john/

This DOESNT work:
http://www.example.com/john

How can I make it work?

In that case you need to remove the trailing slash from the RewriteRule, but then your code will be loopy, so you need to add a RewriteCond to prevent that (i.e., if the request is for profile.php, don’t redirect to profile.php). Something like


# Remove trailing slash from non-existing directory request (which are probably profiles)
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/?$ /$1 [L,R=301]

# Serve profiles through /profile.php
RewriteCond %{REQUEST_URI} !^/profile.php
RewriteRule ^(.*)?$ /profile.php?id=$1

What characters do you accept for profile names btw? It’s better to make a regular expression tuned to your needs instead of this extremely generic one.

Note that your profile.php has to check if the given profile actually exists, and if not, reply with a HTTP 404 File Not Found.

hi, using this im getting a 403.shtml

Did you see I forgot the /!/ in the path? :wink:

(not deliberate by the way, I just noticed it).