Home » Code » How to make vanity URLs using PHP, .htaccess and MySQL

How to make vanity URLs using PHP, .htaccess and MySQL

Posted by on November 16th, 2011

Vanity URL
Vanity URLs have become a staple part of any good online service and are a really good way of helping increase engagement and social sharing of your web app or website. For those of you that don’t know, a vanity URL is usually a direct link to a users profile in the following form – twitter.com/philipbrown.

Here is a quick and easy tutorial for creating vanity URLs for your next project using PHP and .htaccess and an explanation of how those profiles are routed to the correct user in your database using MySQL.

We're going to need a bigger boat

What are we going to need?

Right, to make vanity URLs, you’re going to need the following items in some shape or form.

  • .htaccess
  • profile.php
  • MySQL database

And here is a quick overview of how this process is going to work.

  1. A user will go to your-url.com/username
  2. The .htaccess file will recognise this URL as a vanity URL
  3. The .htaccess file will then pull the profile.php file
  4. The profile.php file will then look up the user based on the URL
  5. The profile.php file will then display the correct user’s profile page

Still with me? Good! Now let’s make what you need.


The .htaccess file

Here is the code that you will need to put in your .htaccess file. At this point I should probably explain what an .htaccess file is…

Basically, the .htaccess file in our case is going to be used to detect and redirect URLs. .htaccess files do a lot, much more than the scope of this tutorial, but that’s all you really need to know at the minute. Have a look at The Ultimate Guide to .htaccess files if you want a more detailed explanation of what an .htaccess file is capable of.

So here’s the code you are going to need to put into your .htaccess file. For a full explanation of the mod_rewrite function, click here.

RewriteEngine on
RewriteCond %{REQUEST_FILENAME}.php -f  
RewriteRule ^([^\.]+)$ $1.php [NC]
RewriteCond %{REQUEST_FILENAME} >""
RewriteRule ^([^\.]+)$ profile.php?user=$1 [L]</pre>

And here’s an explanation of what each line does.

RewriteEngine on

Our first line turns on the rewrite engine.

RewriteCond %{REQUEST_FILENAME}.php -f

The line above checks to see if the request is a file

RewriteRule ^([^\.]+)$ $1.php [NC]

This line turns adds the .php extension. So for example if you URL is /friends, the friends.php file would be called.

RewriteCond %{REQUEST_FILENAME} &gt;""
RewriteRule ^([^\.]+)$ profile.php?user=$1 [L]</pre>

The final two lines pick up the url when it is not a file name, for example, your-url.com/philipbrown and routes it to profile.php?user=philipbrown.

Now that we have the URL in the correct form we can use the selected username to pull the right profile information.


The profile.php file

Next we’re going to create the profile.php file. This file will interpret the URL, pick out the name from the URL and find the user that matches that name.

Here is the first bit of code you will need

$getName = explode("/",$_SERVER['REQUEST_URI']);

This returns an array of strings broken up by the “/”.

Next we need to query the database to find the correct user. This step is assuming that you’ve required your user to pick a vanity URL or a username to be used as the vanity URL.

$result = mysql_query("SELECT * FROM user WHERE url='$getName[3]'");	
$num_rows = mysql_num_rows($result);

In the above query, we are simply selecting the user where the URL field matches what was in the URL.

Next we write a little catch to check to make sure a user was found. If people enter your URL then a name that is not a user in your database you will want to send them to your 404 page.

if($num_rows == 0){
  header ("Location: 404");

Now that you’ve caught any instances that are not in your database you can use the returned data to populate your profile page.

It’s as simple as that!

And here’s an example of a profile page that is using a vanity URL.

If you have an questions, feel free to leave a comment!

Philip Brown

Hey, I'm Philip Brown, a designer and developer from Durham, England. I create websites and web based applications from the ground up. In 2011 I founded a company called Yellow Flag. If you want to find out more about me, you can follow me on Twitter or Google Plus.

  • Make sure you wrap $getName[3] in a mysql_real_escape_string before you run the query- otherwise you’re opening a way for hackers to inject. A regex check might be a good idea too… Shore those defences!

  • Qborreda

    Thanks for the tut, Phillip.
    I had sometimes come to the need of having .htaccess manage several rewrite variables, like a full path, so make some info out of it ..

    Say you would have an url which has something like /state/location/type
    And you would like to connect that to a search to your database, and depending on the different values, you’ll be using a different query .. how would you do that so it would rewrite this on the .htaccess and target .php file?

    Would that only be
    RewriteRule ^([^.]+)$ profile.php?state=$1&location=$2&type=$3 [L] ??

    • Hi glad it helped you!

      There are a number of ways you could achieve what I think you’re aiming for. I would perhaps try and accomplish it using only PHP.

      For example,

      $url = $_SERVER[‘REQUEST_URI’];
      $urlArray = explode(“/”, $url);

      $state = $urlArray[0];
      $location = $urlArray[1];
      $type = $urlArray[2];

      Now you can determine what query you want to run depending on what the url request is.

      Does this help?

  • joe

    hi philip , thanks for the nice tutorial ,
    i have a problem , i did everything you said , and i placed the .htaccess file in the same folder as profile.php , but each time i try to run any php file , i get the same error “Internal Server Error” i dont know what is the problem , but i use localhost:81 , i dont know if this is the problem or what , please help .

    • Hi Joe,

      Sounds like you have a problem in your PHP. Check to make sure you’ve included all the ; at the end of each line as it will probably be something small like that.

      Are you using a text editor with highlighting? That should point out where your problem lies.

      • joe

        thanks for your very fast reply,
        well i am using eclipse , and i checked for typos , i tried your code alot of times , but i cant figure out the problem , and i tried other codes they are not working too , could it be the port 81 thing ?

        • Ahh I see, sorry I misread your first comment.

          Sounds like you’ve got a problem with a configuration setting. Are you using WAMP or MAMP or something similar? Or are you trying to run it on a server?

          I would do a fresh install of WAMP/MAMP or PHP and Apache.

  • kareem ashraf

    how to secure this code from sql injection

  • Bonnu

    Hi philip,

    I need to ask something about that, and it’s may be the most important part of those kind of redirection. Let’s say I have redirection like http://www.mydomain.com/login
    if user try to have exact same username as “login” how could you handle that request? actually possible solution might be minimum character limitation like minimum 6 chars, but it’s not looking elegant since you loose your chance to use more than 6 chars like “/resetpassword”.

    Probably a “banned words” kind of array control would be a solution but then you need to foresee all kind of possibilities which shouldn’t be used.

    Anyway, if you have any kind of elegant approach to that please let me know :)

    Thanks for the article

    • Hi Bonnu

      There is usually many ways to achieve the goal in programming something like this, so the most elegant solution would probably be unique to your code, situation and your website.

      I wouldn’t go down the minimum characters route, because like you said, it’s a bit restrictive and doesn’t really cover all eventualities.

      Having a banned words list is solution because you probably don’t want people to choose the name “login” or “admin” or anything like that.

      You could set rules in htaccess for this to work.

      You could also give precedence to the login page over profile pages.

      There really are many ways you could achieve your goal.

      I would say, find a solution that works. This is the most important thing. Then allow it to evolve as you make it simpler, more elegant or more intuitive to the rest of your website.

      Hope this helps!

      If you want to ask me any specific questions about your code, feel free to ask! :)

    • Mohamad Nasir

      maybe you should define some reserved words

  • Codevils

    very helpful. .. thanks Philip Brown

  • Mohamad Nasir

    this is what im looking for… thx

  • Amit

    Hi Philip, instead of using explode GET function works in an efficient way! :)

    • Hi Amit, great suggestion! I love how there is always more than one way to solve a problem in programming :) thanks for you suggestion!

  • merci

    This is a good post. I have a question though, say, after a user registers, how will you code it in such a way that his username from the database will be the one used as his vanity url. ex.. user registers with name of myName, then will be directed to his vanity url of http://www.mysite.com/myName

    • Hi,

      You would just select which column you want to use in the MySQL statement. So if you wanted to use the user’s username, you would just search for a match on that column.

      • merci

        thanks for the reply.. yeah selecting the username from the database is the easy part, but how do you put it on the url? say $username = ‘mike’. how do you put it http://www.mysite.com/mike... since codeigniter will usually look for a class or function named mike .. it will usually redirect to a 404 error. btw, thank you for helping Philip..

        • Ah I see, you are using codeigniter? You will have to set up a wildcard route (http://ellislab.com/codeigniter/user-guide/general/routing.html) which catches anything that doesn’t match a controller and then search for the username. If a username is found, then you call the user controller and pass the username from the url. The the user is not found you would send a 404 response.

          • merci

            thank you so much for the response, yes i’m using codeigniter… Thank you for heading me in the right direction, appreciate it alot!

          • No problem, glad I could help. Take a look at Laravel (http://laravel.com/) if you’re just starting out. It’s a really nice, modern PHP framework.

            You’ll also be seeing a lot of Laravel tutorials at Culttt going forward!

  • Does it work in WAMP server?

    I am getting 500 error.

    only this is working – RewriteRule ^([^/.]+)/?$ /profile.php?user=$1 [L]

    please help. thank you

    • Yeah it should do.

      Turn on errors and you will be able to see what’s going wrong, rather than just “500 error”. You have probably just missed off a semi-colon!

      • how to turn on the error?
        I exactly did what you had write. but still error. :(

        1 more thing is, how to can i make user’s name link I mane – if 2 or more users have same name then there link will be same, so how to verify from server side? when they register?

        • In your php.ini file under WAMP, change the value of error_reporting.

          You would need to prevent two people from registering the same name

          • ; error_reporting
            ; Default Value: E_ALL & ~E_NOTICE
            ; Development Value: E_ALL | E_STRICT
            ; Production Value: E_ALL & ~E_DEPRECATED

            I got this. now what I need to change?

          • You need to find where error_reporting is set, and change it to error_reporting = E_ALL

          • yes, I have found it but I guess I no need to edit it, because it is already like this.

          • If it’s not commented out, perhaps you are looking at the wrong php.ini file. There’s often more than one

          • WAMP > PHP > php.ini

          • Hmm, I’m not sure, I don’t use WAMP. I would probably have a read through the WAMP documentation.

          • alright. I will check you code after upload my site. thank you man.

  • kay100

    Hi Phil
    How do I get users to input their profile in my website for easy references? Any ideas

  • Arsan Gamal

    thanks it helped me alot .. i was asking for another tutorial plz so if i typed http://www.mysite.com/username/info it get the info of the username as it is stored in the database ?? am i clear ?

  • Justinjohn23
  • Justinjohn23

    Heres my Problem

  • Justinjohn23

    I already Solved this problem below Brother..

    My simple question is
    Can i create multiple .htaccess files ? If possible how?
    Do I need to create different folders?
    Thank you so much !

    • No you should only have one htaccess file and one point of entry for your application.

      All of your page requests should be routed to the index.php file. You then capture the bit at the end of the request to pull the right page.

      So for example, example.com/about would simply pull the about page. example.com/franz would pull the entry from the database because there would be no franz.php file.

      That is what you are need to do, you don’t need multiple htaccess files.

      If that doesn’t make sense, let me know :)

      • Justinjohn23

        Hi Philipbrown Thanks for answering my question.
        I had a problem with regards of dot (.) in my vanity url
        for example i type on my site mysite/franz.philipp( with dot between inside franz and philipp how can i solve this problem john,

        P.s Thanks Bro

        • Hmm, you would have to change the regex to include a dot. I think you would do that by putting a slash in front of the dot because a dot is a special character in regex expressions.

          You are probably better of using a PHP routing package though. This tutorial is pretty old now, I wouldn’t use this technique.

          • Justinjohn23

            do you have any lessons or idea where i can find a better tutorial for same as this? Thanks man for giving a time to answer my question
            You really Good :p

          • haha thanks, you should you Slim, it’s really good http://www.slimframework.com/

          • Justinjohn23

            Thanks Man :P

          • No problem :)

  • Stephen

    Hello Philiph,

    Thanks for a great tutorial. I however can’t figure out how to make it work for my website http://www.kenyaschoolsdownloads.com A user registers with a username which gets an ID in the database but they choose a NAME to use on their profile page ( This name doesnt go to any database).

    How can I get the links to point to kenyaschoolsdownloads.com/profilename other than to kenyaschoolsdownloads.com/view_profile.php?id=ID Number?

    I can send you the script to look at if that would be ok with you. Thanks

    • You would have to store it in the database. There would be no other way really. Why don’t you store the name in the database? How do you persist it between visits?

  • arindambarman

    Why $getName[3]?
    What’s up with [3]

    • $getName is an array and you want to get the value at the 3 position.

      • JesseChisholm

        re: What’s up with [3]?
        This comes from “http://yourdomain/username” getting broken into
        by the explode call. If your vanity URL format is more complex than that, you might need a different index. Eg., “http://yourdomain/profiles/username” would use [4] and an appropriately modified .htaccess file.

        • Mauricio R. Duarte

          and how would be an approprietaly modified .htaccess file ?
          My file likes your example.

          • JesseChisholm

            The key line is the “RewriteRule REGULAREXPRESION REPLACEMENT [OPTIONS]” line. What is “appropriate” is entirely up to _you_. The original article has an expression that matched for anything that did NOT have a period in it, and replaced that with the “profile.php?username=$1” string, where $1 is whatever it matched. Your regular expression all depends on what you want to match for your vanity URLs. Your replace expression all depends on what you want your vanity URLs to translate into on your server’s file/directory structure. Read up on the ReWriteRule in all its glory: http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html

          • JesseChisholm

            So, in my example: “http://yourdomain/profiles/username” the line might be: “ReWriteRule ^profiles/([^.]+)$ profiles.php?username=$1 [L]”

          • Thanks Jesse :D great explanation! :)

          • Mauricio R. Duarte

            in this article, if the url go to a http://yourdomain.com/expression and is not a profile or a page.php, sometimes i have directories. But how can add a rule for the condition of folders too ?
            Best regards

          • JesseChisholm

            You really do need to go study the entire ReWriteRule concept at http://httpd.apache.org/docs/current/mod/mod_rewrite.html because there are way to many ways of using it for a comment in a forum to explain them all. But it boils down to: use regular expressions to match what YOU want to match, rewriting them to what YOU want them to be. There are options to restrict the match to files or directories. But this article is about matching things that DO NOT EXIST and mapping the the things that DO exist.

  • Tony Arenas

    Can this technique be used for a site made in codeigniter?

  • Vikas Yadav

    Thank you very much for this guide!

    • No problem, glad you found it useful! :)

      • Vikas Yadav

        Hi, Came here again with a doubt,
        why complicate this thing when it can be easily done by editing the .htaccess once?
        In my project instead of making the php vanity compatible scripts(getting the url and splitting and all), i directly re write the URLs as VANITY URLs, by just a single line in the htaccess.
        Why you think this method is more appropriate ?

        PS: noob here.

        • Personally I’d prefer to have the logic in PHP, rather than .htaccess, but saying that, I’m all for choosing the simpler solution :)

  • Hello Philip

    Hi Philip, I have followed the same steps as you. But I get an error..
    My question is “Do I have to have a url for each user already, before selecting ????” Thanks in advance.

  • Hi

    Nice quick introduction. My main concern is security. Would it be possible to use sql as part of the URL and then inject the database? For example: http://yourdomain.com/profile/someSQLcommands

  • anonymous

    vulnerable to SQL Injection!!

  • Egor Kolesnikov

    Hi, man, thanks. I only got one question…
    Will google search in mysql db and give the right url?
    So if I typed “username” in google will it give me the url / link like this “mysite.com/usename” ?

    • Yes if Googlebot can crawl and index your profile pages.