Using HTACCESS for Pretty URLS

Using htaccess Files for Pretty URLS

Jul 31st in Other by Noah Hendrix

Continuing our review of htaccess files, today we'll examine how to use mod_rewrite to create pretty URLs.

PG

Author: Noah Hendrix

Noah is a Computer Science student at the University of Kansas. His interests include web development in PHP/MySQL and Ruby on Rails. He obsessively follows Tech Startups and has been known to have his own entrepreneurial ambitions. His development environment of choice is Mac OSX using a combination of TextMate and Coda. Find out more about him on twitter (@noahhendrix) or facebook.com/noahhendrix.

Benefits of Formatted URLs

While some claim pretty URLs help in search engine rankings, the debate here is fierce, we can all agree that pretty URLs make things easier for our users and adds a level of professionalism and polish to any web application. I could go over all the theoretical reasons for this, but I like real-world examples better. Like it or hate it we all must admit that Twitter is a wildly popular web application and part of the reason for that is most certainly how it formats URLs. I can tell anyone in the know that my Twitter username is noahhendrix, and they know my profile can easily be found at twitter.com/noahhendrix. This seemingly simple concept has vast effects in the popularity of your application.

Just to put things in perspective we can look at another popular social networking website, Facebook. Since the site launched in 2004 the profile system has grown and evolved to better tailor to users, but one glaring hole was the URL to a profile. From the time I registered with Facebook my profile was at the URL http://www.facebook.com/profile.php?id=1304880680. That is quite a mouth full, and just recently it appears Facebook has realized that and they launched Facebook vanity URLs. Now I can share my Facebook profile by telling people my Facebook username is "noahhendrix", which they know can be found by going to facebook.com/noahhendrix. While the odds are that we won't have an application as popular as Facebook, we can still borrow a few pages from their book.

Quick Overview

A quick overview before we dive into code, in today's tutorial we will go over two slightly different methods of creating pretty URLs using HTACCESS. The difference between the methods is whether Apache or PHP is doing the heavy lifting to break the URL apart for parsing. I want to point out that mod_rewrite tutorials are almost as old as the internet itself and this is not the first. At the end I will use one of the methods to create a simple application to show how these solutions would look in a real-live website (well not 100% production quality). The service we will create is a URL shortener that can mirrors the functionality of such sites like bit.ly, TinyURL, or su.pr. So without anymore fluff let us look at the code.

Using Apache

First, we can place all of our code in Apache .htaccess files. This could look something like this:

  Options +FollowSymLinks
  RewriteEngine On

  RewriteCond %{SCRIPT_FILENAME} !-d
  RewriteCond %{SCRIPT_FILENAME} !-f

  RewriteRule ^users/(\d+)*$ ./profile.php?id=$1
  RewriteRule ^threads/(\d+)*$ ./thread.php?id=$1

  RewriteRule ^search/(.*)$ ./search.php?query=$1

Let's start at the top and work our way down to better understand what is going on here. The first line sets the environment up to follow symbolic links using the Options directive. This may or may not be necessary, but some web hosts use symlinks (similar to alias in MacOSX or shortcuts is Windows) for common HTTP request errors and these are usually symlinked files, or at least this is how I understand the reasoning. Next we tell Apache we are going to use the Rewrite Engine. The next two lines are very, very important it restricts rewriting URLs only to paths that do not actually exists. This prevents the rules below from matching example.com/images/logo.png for example. The first prevents existing directories with the !-d flag and the second with !-f means ignore existing files.

The next three lines are the actual URL rewriting commands. Each line creates a rule that tries to match a regular expressions pattern against the incoming URL. Regular expressions, at least for me, are a hard set of rules to remember but I always find it helpful to use this tutorial by Nettut's own Jeffery Way and the tool he recommends. I found it easy to type in sample URLs we want to match and then try to hack together the pattern.

The first argument is the pattern, between the caret and dollar sign. We tell Apache we want URLs asking for the users directory (an artificial directory, doesn't have to actually exist) followed by a / and any length of numbers. The parenthesis create a capture group, you can use as many of these as you want, they serve as variables that we can then transplant into our rewrite. The asterisk means the user can enter whatever they want, and it won't affect the rewrite, this is primarily to handle a trailing slash so example.com/users/123 is the same as example.com/users/123/ as users would expect.

The second argument is the path we want to actually call, this unlike the first must be a real file. We tell Apache to look in the current directory for a file called profile.php and send the parameter id=$1 along with it. Remember the capture group earlier? That is where we get the variable $1, capture groups start at one. This creates a URL on the server like example.com/profile.php?id=123.

This method is great for legacy web applications that have existing URL structures that prevent us from easily rewriting the backend to understand a new URL schema because to the server the URL looks the same, but to the user it looks much nicer.

Using PHP

This next method is great for those who don't want to distribute too much logic to Apache and feel more comfortable in PHP (or similar scripting languages). The concept here is capture any URL the server receives and push it to a PHP controller page. This comes with the added benefit of control, but greater complexity at the same time. Your HTACCESS file might look something like this:

  Options +FollowSymLinks
  RewriteEngine On

  RewriteCond %{SCRIPT_FILENAME} !-d
  RewriteCond %{SCRIPT_FILENAME} !-f

  RewriteRule ^.*$ ./index.php

Everything is the same as above, except the last line so we will skip to it. Instead of creating a capture group we just tell Apache to grab every URL and redirect it to index.php. What this means is we can do all of our URL handling in PHP without relying too much on stringent URL paths in HTACCESS. Here is what we might do at the top of our index.php file to parse out the URL:

  <?php
    #remove the directory path we don't want
    $request  = str_replace("/envato/pretty/php/", "", $_SERVER['REQUEST_URI']);

    #split the path by '/' 
    $params     = split("/", $request);
  ?>

The first line is not necessary unless you application doesn't live at the root directory, like my demos. I am removing the non-sense part of the URL that I don't want PHP to worry about. $_SERVER['REQUEST_URI'] is a global server variable that PHP provides and stores the request URL, it generally looks like this:

  /envato/pretty/php/users/query

As you can see it is basically everything after the domain name. Next we split up the remaining part of the virtual path and split it by the / character this allows us to grab individual variables. In my example I just printed the $params array out in the body, of course you will want to do something a little more useful.

One thing you might do is take the first element of the $params array and include a file by that same name and within in the file you can use the second element in the array to execute some code. This might look something like this:

	 <?php
	   #keeps users from requesting any file they want
	   $safe_pages = array("users", "search", "thread");
	   
	   if(in_array($params[0], $safe_pages)) {
	     include($params[0].".php");
	   } else {
	     include("404.php");
	   }
	 ?>

WARNING: The first part of this code is unbelievably important! You absolutely must restrict what pages a user can get so they don't have the opportunity to print out any page they wish by guessing at file names, like a database configuration file.

Now that we have the soapbox out of the way let's move on. Next we check if the requested file is in the $safe_pages array, and if it is we include otherwise will include a 404 not found page. In the included page you will see that you have access to the $params array and you can grab whatever data from it that is necessary in your application.

This is great for those who want a little more control and flexibility. It obviously requires quite a bit extra code, so probably better for new projects that won't require a lot of code to be updated to fit the new URL formats.

A Simple URL Shortner

This last part of the tutorial is going to let us put some use to the code we went over above, and is more or less a "real-life" example. We are going to create a service called shrtr, I made up this name so any other products with this name are not associated with the code I am posting below. Note: I know this is by far not an original concept, and is only meant for demonstration of mod_rewrite. First let's take a look at the database:

As you can see this is very straightforward, we have only 4 columns:

  • id: unique identifier used to reference specific rows
  • short: unique string of characters appended to the end of our URL to determine where to redirect
  • url: the URL that the short url redirects to
  • created_at: a simple timestamp so we know when this URL was created

The Basics

Next, let's go over the six files we need to create for this application:

  • .htaccess: redirects all short urls to serve.php
  • create.php: validates URL, creates shortcode, saves to DB
  • css/style.css: holds some basic styling information
  • db_config.php: store variables for database connections
  • index.php: The face of our application with form for entering URL
  • serve.php: looks up short URL and redirects to actual URL

That is all we need for our basic example. I will not cover index.php or css/style.css in very great detail because they are have no PHP, and are static files.

# index.php
----
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Makes URLs Shrtr</title>
    <link type="text/css" rel="stylesheet" href="./css/style.css" />
	</head>
	<body>
	 <div id="pagewrap">
  	 <h1>shrt<span class="r">r</span>.me</h1>
  	 
  	 <div class="body">
  	   <form action="./create.php" method="post">
  	   
  	     <span class="instructions">Type your URL here</span>
  	     <input name="url" type="text" />
  	     <input type="submit" value="shrtr" />
  	   
  	   </form>
  	 </div>
	   
	 </div>
	</body>
</html>

The only real interesting to note here is that we submit the form with a field called URL to create.php.

# css/style.css
----
/* reset */
* {
  font-family: Helvetica, sans-serif;
  margin: 0;
  padding: 0;
}

/* site */
html, body { background-color: #008AB8; }
a { color: darkblue; text-decoration: none;}

  #pagewrap {
    margin: 0 auto;
    width: 405px;
  }
  
    h1 {
      color: white;
      margin: 0;
      text-align: center;
      font-size: 100px;
    }
      h1 .r { color: darkblue; }
    
    .body {
      -moz-border-radius: 10px;
      -webkit-border-radius: 10px;
      background-color: white;
      text-align: center;
      padding: 50px;
      height: 80px;
      position: relative;
    }
    
      .body .instructions {
        display: block;
        margin-bottom: 10px;
      }
      .body .back {
        right: 15px;
        top: 10px;
        position: absolute;
      }
      
      .body input[type=text] {
        display: block;
        font-size: 20px;
        margin-bottom: 5px;
        text-align: center;
        padding: 5px;
        height: 20px;
        width: 300px;
      }

That is all very generic, but makes our application a little more presentable.

The last basic file we need to look at is our db_config.php, I created this to abstract some of the database connection information.

# db_config.php
----
<?php

  $database = "DATABASE_NAME";
  $username = "USERNAME";
  $password = "PASSWORD";
  $host     = "localhost";

?>

You need to replace the values with what works in your database, and host is probably localhost, but you need to double check with your hosting provider to make sure. Here is the SQL dump of the table, url_redirects that holds all the information we showed above:

--
-- Table structure for table `url_redirects`
--

CREATE TABLE IF NOT EXISTS `url_redirects` (
  `id` int(11) NOT NULL auto_increment,
  `short` varchar(10) NOT NULL,
  `url` varchar(255) NOT NULL,
  `created_at` timestamp NOT NULL default CURRENT_TIMESTAMP,
  PRIMARY KEY  (`id`),
  KEY `short` (`short`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

Creating the Short URL

Next lets look at the code necessary to create our short URL.

# create.php
----
<?php
  require("./db_config.php");
  
  $url = $_REQUEST['url'];
  
  if(!preg_match("/^[a-zA-Z]+[:\/\/]+[A-Za-z0-9\-_]+\\.+[A-Za-z0-9\.\/%&=\?\-_]+$/i", $url)) {
    $html = "Error: invalid URL";
  } else {
    
    $db = mysql_connect($host, $username, $password);
    
      $short = substr(md5(time().$url), 0, 5);
    
      if(mysql_query("INSERT INTO `".$database."`.`url_redirects` (`short`, `url`) VALUES ('".$short."', '".$url."');", $db)) {
        $html = "Your short URL is<br />shrtr.me/".$short;
      } else {
        $html = "Error: cannot find database";
      }
    
    mysql_close($db);
  }
?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Makes URLs Shrtr</title>
    <link type="text/css" rel="stylesheet" href="./css/style.css" />
	</head>
	<body>
	 <div id="pagewrap">
  	 <h1>shrt<span class="r">r</span>.me</h1>
  	 
  	 <div class="body">
  	   <?= $html ?>
  	   <br /><br />
  	   <span class="back"><a href="./">X</a></span>
  	 </div>
	   
	 </div>
	</body>
</html>

Now we are getting a bit more complex! First we need to include the database connection variables we created earlier, then we store the URL parameter sent to us by the create form in a variable called $url. Next we do some regular expressions magic to check if they actually sent a URL, if not we store an error. If the user entered a valid URL we create a connection to the database using the connection variables we include at the top of page. Next we generate a random 5 character string to save to the database, using the substr function. The string we split up is the md5 hash of the current time() and $url concatenated together. Then we insert that value into the url_redirects table along with the actual URL, and store a string to present to the user. If it fails to insert the data we store an error. If you move down into the HTML part of the page all we do is print out the value of $html, be it error or success. This obviously isn't the most elegant solution but it works!

Serving the Short URL

So we have the URL in the database let's work on serve.php so we can actually translate the short code into a redirect.

<?php
  require("./db_config.php");

  $short = $_REQUEST['short'];

  $db = mysql_connect($host, $username, $password);    
    $query = mysql_query("SELECT * FROM `".$database."`.`url_redirects` WHERE `short`='".mysql_escape_string($short)."' LIMIT 1", $db);
    $row = mysql_fetch_row($query);

    if(!empty($row)) {
      Header("HTTP/1.1 301 Moved Permanently");
      header("Location: ".$row[2]."");
    } else {
      $html = "Error: cannot find short URL";
    }

  mysql_close($db);
?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Makes URLs Shrtr</title>
    <link type="text/css" rel="stylesheet" href="./css/style.css" />
	</head>
	<body>
	 <div id="pagewrap">
  	 <h1>shrt<span class="r">r</span>.me</h1>

  	 <div class="body">
  	   <?= $html ?>
  	   <br /><br />
  	   <span class="back"><a href="./">X</a></span>
  	 </div>

	 </div>
	</body>
</html>

This one is very similar to create.php we include the database information, and store the short code sent to us in a variable called $short. Next we query the database for the URL of that short code. If we get a result we redirect to the URL, if not we print out an error like before.

As far as PHP goes that is all we need to do, but at the moment to share a short URL users must enter this, http://shrtr.me/server.php?short=SHORT_CODE not very pretty is it? Let's see if we can't incorporate some mod_rewrite code to make this nicer.

Pretty-ify With HTACCESS

Of the two methods I wrote about at the beginning of the tutorial we will use the Apache one because this application is already created without considering any URL parsing. The code will look something like this:

  Options +FollowSymLinks
  RewriteEngine On

  RewriteCond %{SCRIPT_FILENAME} !-d
  RewriteCond %{SCRIPT_FILENAME} !-f


  RewriteRule ^(\w+)$ ./serve.php?short=$1

Skipping to the RewriteRule we are directing any traffic that doesn't already have a real file or directory to serve.php and putting the extension in the GET variable short. Not to bad no go try it out for yourself!

Conclusion

Today we learned a few different ways to utilize mod_rewrite in our application to make our URLs pretty. As always I will be watching over the comments if anybody has trouble, or you can contact me on twitter. Thanks for reading!


Related Posts

Check out some more great tutorials and articles that you might like

Enjoy this Post?

Your vote will help us grow this site and provide even more awesomeness

Plus Members

Source Files, Bonus Tutorials and
More for $9 a month for all TUTS+
sites in one subscription.

Join Now

User Comments

( ADD YOURS )
  1. PG

    Yoosuf July 31st

    First hura, its really awsome!!!

    ( Reply )
  2. PG

    Muhammad Adnan July 31st

    i like it .. carry on man ..!

    ( Reply )
  3. PG

    Nick July 31st

    Very nice! I’ve always wondered how url shortening services work thanks a lot for showing this :) . I was also stuck on mod_rewrite and how it worked so this is 2 in 1 for me haha

    ( Reply )
  4. PG

    Zy July 31st

    Not so bad for a start.

    ( Reply )
  5. PG

    Evan Byrne July 31st

    I find that using $_SERVER['PHP_SELF'] instead of $_SERVER['REQUEST_URI'] is a little more reliable, but either one will work in this case.

    ( Reply )
  6. PG

    Dave B. July 31st

    Nice Tutorial…If you have a wordpress blog and want a great plugin that does url shortening and a whole lot more then click my name for more info.

    ( Reply )
  7. PG

    techietim July 31st

    I know it was hypothetical, but having:

    $request = str_replace(”/envato/pretty/php/”, “”, $_SERVER['REQUEST_URI']);

    wouldn’t allow you do go to:

    http://example.com/envato/pretty/php/test/envato/pretty/php/

    ( Reply )
    1. PG

      Ryan July 31st

      It’s not suppose to.. it was just so he could get the last two folders into an array.

      ( Reply )
      1. PG

        techietim August 1st

        Okay then, but say if your root folder was /php/, and you still used the str_replace function, it wouldn’t work:

        $request = str_replace(”/php/”, “”, $_SERVER['REQUEST_URI']);

        http://example.com/php/category/php/

  8. PG

    webn July 31st

    Nice topic selection and timely helped for me.

    ( Reply )
  9. PG

    mark July 31st

    very nice.. thank will use this as an addon to a page of mine now..

    ( Reply )
  10. PG

    Abraham July 31st

    This is a good introductory tut, well done!
    I’m not 100% sure if I am correct, but I believe the !-f flag would mean that references to files that do not exist but are supposed to (such as incorrect references to images, css or javascript files) would match too, and the request would be redirected to the php file.
    Not that it would cause problems for most people, but it might in the long run, if people use this to build upon – especially if the php script keeps track of the user’s history (last visited pages).
    I would suggest something like the following in the .htaccess file to prevent this (before the redirect to the php file):
    RewriteCond %{REQUEST_FILENAME} ^(.+)\.(css|js|png|gif|jpe?g|ico)$ [NC]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule .* – [L]

    ( Reply )
    1. PG

      Ivica August 12th

      Hi!
      My .htaccess file look like this:

      Options +FollowSymLinks
      RewriteEngine On

      RewriteCond %{REQUEST_FILENAME} ^(.+)\.(css|js|png|gif|jpe?g|ico)$ [NC]
      RewriteCond %{REQUEST_FILENAME} !-f
      RewriteRule .* – [L]

      RewriteCond %{SCRIPT_FILENAME} !-d
      RewriteCond %{SCRIPT_FILENAME} !-f
      RewriteRule ^vijest/(\d+)*$ ./?page=vijest&id=$1
      RewriteRule ^rezultati/(\d+)*$ ./?page=rezultati&arhiva=$1

      and it redirects me where i want it to, but without css, jpg and js files.
      What is wrong, I can’t figure it out?!

      ( Reply )
  11. PG

    crysfel July 31st

    thanks dude! this is good

    ( Reply )
  12. PG

    Lee July 31st

    I’m actually certain that twitter doesn’t run off of a apache backend, wouldn’t it be more correct to call this article ‘Using RewriteEngine for Pretty URLS’?

    but of course, I’m digressing.

    PS: RewriteEngine can do some pretty amazing regex as well.

    ( Reply )
  13. PG

    Simon Vansintjan July 31st

    This is bookmarked. Thanks a bunch.

    ( Reply )
  14. PG

    Enatom July 31st

    This is put in my delicous, and would need this very soon.

    thanks man.

    ( Reply )
  15. PG

    Dario Gutierrez July 31st

    Excellent!

    ( Reply )
  16. PG

    Cody July 31st

    Very nice tutorial…..well done. Useful principles and techniques.

    ( Reply )
  17. PG

    Santana July 31st

    very interesting thank u noah

    ( Reply )
  18. PG

    Rohan July 31st

    Stuff like this has fast made me feel that nettuts is the best of the tuts+ sites!

    ( Reply )
  19. PG

    Dev Words July 31st

    Nice, I like the PHP trick :)

    ( Reply )
  20. PG

    Miles Johnson July 31st

    Sorry, but a lot of this is wrong (even though it works) and can be done with half the code and twice as easier.

    Ill write a post about it.

    ( Reply )
  21. PG

    Miles Johnson July 31st

    Ok quick example:

    URL: /forums/view_topic/1
    Mod Rewrite:

    RewriteRule ^forums/([-a-zA-Z0-9_]+)/([0-9]+)/?$ forums.php?page=$1&id=$2 [QSA]

    All you have to do in the php is use $_GET.

    $_GET['page'] would display view_topic and $_GET['id'] would be 1.

    Enjoy.

    ( Reply )
    1. PG

      Abraham August 1st

      The final part of Noah’s article already talks about handling requests in this way, using $_GET. But I think his code is a little better than your example as his is dynamic, whereas your example is for /forums/ only.

      ( Reply )
  22. PG

    Lamin Barrow July 31st

    I am sure a lot of people must have been expecting this article for a long time now. Finally here it is and it’s great read.Thanks for the tutorial Noah.

    ( Reply )
  23. PG

    RottNKorpse August 1st

    Thank you very much for the tutorial. I am fairly familiar with mod_rewrite so I have been using it for a while to build all kinds of stuff but when I used my basic domain without a leading artificial directory it would error my existing files and directories but turns out I simply forgot to include

    RewriteCond %{SCRIPT_FILENAME} !-d
    RewriteCond %{SCRIPT_FILENAME} !-f

    and now all of my rewrites are working perfectly without hendering any of my existing files. (that is probably basics but somehow I missed that) So thanks again although I have already had a lot of frustration with this :) It has saved me from any further.

    ( Reply )
  24. PG

    Abraham August 1st

    I think the second method (redirect all requests to PHP file, use $_GET to get the URL) is much better as you then have a more dynamic script and can for instance store the whitelist in a database, with permissions, etc.

    Continuing on my other comment yesterday, I’d like to build a little more on Noah’s good script – the final part of my .htaccess (for an MVC-based framework) looks like this:

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule .* index.php?route=$0 [L]

    The index.php file then handles the request:

    $route = $_GET['route'];
    $route = rawurldecode($route);
    $route = trim($route, ‘/\\’);
    $args = explode(’/', $route);

    The $args are then mapped to the necessary controller class if it is found (eg. controllers/forum.php) and necessary function in that controller (eg. function view_topic()) who obviously have more specificity, and can better decide how to handle the request from there – most times this will be based on the rest of the $args – eg. ‘1′ – checks if a topic with that ID exists in the database & serves it etc.

    Also, if the function (eg. view_topic) doesn’t exist, a default function (in the forum controller) can be run, which helps the person try find what they were looking for (something to do with forums obviously), etc.
    Or if the controller (eg. forum) doesn’t exists, a fallback controller (eg. error_404) can be run.

    PHP gives you dynamic control over the incoming request, which the .htaccess file can’t.

    Regards

    ( Reply )
  25. PG

    claudio August 1st

    Excellent, thanks!

    ( Reply )
  26. PG

    Showfom August 1st

    Using Nginx:

    if (!-d $uri){
    set $rule_0 1$rule_0;
    }
    if ($rule_0 = “1″){
    rewrite ^/users/(\d+)*$ /./profile.php?id=$1;
    }
    rewrite ^/threads/(\d+)*$ /./thread.php?id=$1;
    rewrite ^/search/(.*)$ /./search.php?query=$1;

    ( Reply )
  27. PG

    Fynn August 1st

    I’ve waited a long time for a good tutorial about url rewriting! thanks :)

    ( Reply )
  28. PG

    ciprian August 1st

    This is a grate tutorial ! i’m waiting for more htaccess tutorials.

    ( Reply )
  29. PG

    Mohamed Aslam August 1st

    Nice tut!
    Thank you!

    ( Reply )
  30. PG

    psdmed August 1st

    Wow i was waiting for a similar tutorial,i need a cup of thea and a lot of concentration :D thanks man..

    ( Reply )
  31. PG

    David Moreen August 1st

    I am going to buy that domain, hehe.

    ( Reply )
  32. PG

    tim August 1st

    just amazing post, it’s what I was looking for !!
    Greats from france :)

    ( Reply )
  33. PG

    Rashaud Teague August 1st

    just use this for URL Shortening http://rsurl.us/dev

    ( Reply )
  34. PG

    dave August 1st

    much easier to manage in virtual directory file

    ( Reply )
  35. PG

    leo rapirap August 1st

    I’ll try it with one of my projects.
    Thanks!

    ( Reply )
  36. PG

    RottNKorpse August 2nd

    ok I still have a bit of frustration… :(

    how you set the rewrites would work indeed but what I am wanting to do is make the setup be something like

    url entered into browser:
    http://example.com/value/artdir (artdir = artificial directory)

    rewrite code:
    ^(.*)/artdir artdir.php?param=$1

    however I also want another rewrite for when there isnt an artdir.

    url:
    http://example.com/value

    rewrite:
    ^(.*)$ something.php?param=$1

    The first one works just fine until I add the second one…once the rewrite for without an artdir is added the first one is overwrote and when you put in http://example.com/value/artdir the result becomes “value/artdir” as if the first one no longer applies or it sees /artdir as apart of the value it is suppose to pull.

    How can you separate similar rewrites like that? As long as I can make it stop at a certain point, right before the “/” then it should work but right now it just includes it all. (I have already tried hundreds of things as well as watch the tutorials on RegEx from Jeff Way.)

    Any ideas?

    ( Reply )
    1. PG

      Abraham August 4th

      I’m not sure if I understand completely, so I’ll try give an answer that covers the bases :

      For a URL like “http://example.com/value/artdir”, if you only want the ‘value’ part as the param, and the ‘artdir’ part is always literally the string ‘artdir’ (that’s the way I understand your post, though can’t see why you’d want that), I think you’re looking for something like the following:

      RewriteCond %{REQUEST_FILENAME} !-f
      RewriteRule ^(.+)/artdir/?$ artdir.php?param=$1 [L]

      RewriteCond %{REQUEST_FILENAME} !-f
      RewriteRule .* something.php?param=$0 [L]

      But for something more dynamic and scalable:
      If you want a certain redirect when the URL is of the form:
      “/anything1/anything2″ ,
      but a different redirect if the URL just looks like
      “/anything1″
      without the “/anything2″ part, I would suggest the following as the first RewriteRule instead (and then handle the request with your artdir.php file) :

      RewriteRule ^(.+)/(.+)/?$ artdir.php?value=$1&rest=$2 [L]

      ( Reply )
  37. PG

    Rishi Patel August 2nd

    Just in the time i need it.

    ( Reply )
  38. PG

    blazedd August 2nd

    Awesome post! I have been looking for something like this. i don’t care for using GET all the time. I will look into balancing the code a little better and see what i can do. I hate using .htaccess so will definitively look into the PHP mode a lot more!

    ( Reply )
  39. PG

    LionKing August 2nd

    Thanks for this tutorial

    ( Reply )
  40. PG

    dojo Man August 2nd

    good tutorial

    ( Reply )
  41. PG

    Anton Agestam August 2nd

    This is what I’m usually using. :) OK tut

    ( Reply )
  42. PG

    Manuel August 2nd

    Very nice tut :) )

    ( Reply )
  43. PG

    Srinivas Tamada August 2nd

    More .htaccess tutorials with examples

    http://9lessons.blogspot.com/2009/01/htaccess-tutorials.html

    ( Reply )
  44. PG

    Benjamin Reid August 3rd

    Awesome tut’. Is this how WordPress does permalinks?

    ( Reply )
  45. PG

    biniyam August 3rd

    hi i develop my site with routing system and using MVC architecture and my home page is http://www.ejobob.net/job. i used .htaccess to make all routing in pass through index.php. it works fine in my localhost but when i host it it didnt work and i dont understand ? do u have something for me?

    ( Reply )
    1. PG

      Abraham August 4th

      Firstly, the url references on your site seem to be incorrect – they start with “///”, but it should just be “/”

      eg. “///public/js/validate.js” should be “/public/js/validate.js”

      If you use the $_GET method which Noah mentions at the end (plus read my other comments earlier), you shouldn’t have a problem with your routing system.

      Hope it helps you.

      ( Reply )
  46. PG

    Martyn Web August 3rd

    I was looking for an article on how to do this but I can’t see the really benefit if your page extensions end .php or html and so on. Its good to know where to come though should I need to do this.

    Thanks

    ( Reply )
  47. PG

    Michael August 3rd

    Great tut!

    ( Reply )
  48. PG

    Les August 3rd

    This method of search engine friendly urls would be okay for simple web sites however when you come to a more complex site structure, you’d be screwed as to how you would scale it up.

    The easiest solution, and the better solution to begin with would be to implement some sort of “routes”, like RoR did – it was RoR in fact that kicked the whole “routes” thing off anyway, about the only good thing to come from RoR in my opinion.

    There are quite a few implementations kicking about now for PHP so go google, and stay away from this method as it will be scale… be warned (been there, done that, etc).

    ( Reply )
  49. PG

    wayno007 August 3rd

    Thanks, Noah. Another great tut.

    ( Reply )
  50. PG

    Juan August 3rd

    Very nice! Thanks

    ( Reply )
  51. PG

    Ben Williams August 3rd

    im trying to get this to work on one of my sites but it comes up as a 404 error every time or a blank page.
    I have my example site here.
    http://share-my.info/
    I just copied the code and its not working.
    What should i do.

    ( Reply )
  52. PG

    Kasper August 3rd

    I certainly like this a lot! And I also like the php part alot, but regarding the php.

    Lets say I have some file sructures as
    pages/mainpages and so on.php
    pages/admin/admin pages.php
    pages/error/404 403 405 and so on.php
    pages/party/assign status and so on.php

    How would I with the smartest way pick what file in what folder?
    I suppose making an array with dirs and then specifying them with the url somehow?

    $request = $_SERVER['REQUEST_URI'];
    $params = split(”/”, $request);
    $safe_pages = array(”contact”, “home”, “prices”, “portfolio”);
    $dirs = array(”errors”, “admin”);

    if(in_array($params[1], $safe_pages)) {
    include($params[0].”/”.$params[1].”.php”); // Something like that?
    } else {
    include(”404.php”);
    }

    Or is there a more smart way to structure all this so also stuff as news/category/newstitle also will be smart implemented??

    Best regards
    Kasper

    ( Reply )
  53. PG

    Ben Williams August 3rd

    im trying to get this to work on one of my sites but it comes up as a 404 error every time or a blank page.
    I have my example site here.
    http://share-my.info/
    I just copied the code and its not working.
    What should i do.

    ( Reply )
  54. PG

    Jake August 4th

    Great introduction to htaccess for beginners, creating pretty URLs is very important, especially for SEO, so this article has been very helpful

    ( Reply )
  55. PG

    dhie August 4th

    bookmarked.
    nice tutorial. thank :-)

    ( Reply )
  56. PG

    Michael August 6th

    Finally!!

    ( Reply )
  57. PG

    Clem August 8th

    thanks Noah !

    I’m trying to implement the .htaccess + PHP solution for my website.
    Everything works fine so far except for the fact that when there more than one parameter, the pages don’t seem to load the javascript and css files included in the tag.

    http://www.mysite.com/something —> this works fine
    http://www.mysite.com/something/something_more —> this doesn’t work

    any idea what might be wrong ? (So far I’ve run everything locally using MAMP)

    thank you,
    Clem

    ( Reply )
  58. PG

    Joe August 10th

    Nice Tutorial. Wish i could use it myself, but unfortunately i chose ASP instead of PHP (damn me) XD

    Keep up the good work!

    ( Reply )
  59. PG

    deviantz August 13th

    cool man! thanks for sharing this! keep it up!

    ( Reply )
  60. PG

    tanel August 16th

    good code but…. if you are using substr of md5, you might eventually experience collision. 32 bytes is pretty sure identical but 5 first chars might match.

    i used similar code and this goes like this:

    if(!isset($_GET['id'])){
    //hash
    $hash = md5(time().microtime()+$_SERVER['HTTP_USER_AGENT']);
    //start
    $i = 4;
    while($iq($q);
    $fetch = mysql_fetch_array($res);
    if($fetch[0] == 0){
    $hash = $k2;
    break;
    }
    }
    with this code you’ll get 5 chars “id’s” but if current code exists it will take 6th char also and so on… this few querys to mysql aint very load-”ishh” to database also, i think :)
    keep up the good work ;)

    ( Reply )
  61. PG

    tanel August 16th

    sorry, pasteing went wrongor just my silly touch-pad again :(

    $id = md5(time().microtime()+$_SERVER['HTTP_USER_AGENT']);
    $i = 4;
    while($iq($q);
    $fetch = mysql_fetch_array($res);
    if($fetch[0] == 0){
    $id = $k2;
    break;
    }
    }

    ( Reply )
  62. PG

    rat32 August 17th

    wow great

    ( Reply )
  63. PG

    natura August 28th

    Hello. I have a problem with a site and i was wondering if you could help me.
    I want to rewrite www[dot]grindul-lupilor[dot]ro/index.php?limba=engleza (I also have four more languages)
    into this: www[dot]grindul-lupilor[dot]ro

    how can i do it?

    thank you in advance

    ( Reply )
  64. PG

    natura August 28th

    Any idea ? thanks again

    ( Reply )
  65. PG

    Nabeel September 1st

    I have setup redirection for nitrogen.wmskins.com to http://www.wmskins.com/index.php?file=minicms/cms&id=1, its working fine. but the url in the address bar also changes, I would like that url i.e. nitrogen.wmskins.com remains same in the address bar. How to achieve that?

    ( Reply )
  66. PG

    mak September 11th

    hi frnd great tutorial about short url, but i have one doubt is it possible of adding multiple urls at a time and getting the result for each url link respectively. Thank you .

    ( Reply )
  67. PG

    Loy21 October 22nd

    I guess it is just funny, huh. ,

    ( Reply )
  68. PG

    rook October 28th

    http://doitbigtickets.com/ResultsGeneral.aspx?kwds=New+York+Yankees

    Above is my site URL and i tried the above .htaccess recommendation but still it does’nt work. Can somebody please help?

    ( Reply )
  69. PG

    Pradeep Vanparia November 9th

    Very nice..

    ( Reply )
  70. PG

    PRASHANT SHEKHER November 18th

    when i am adding Your htaccess file why my index.php file not run.WHY????

    PLZ PLZ PLZ PLZ HELP ME

    ( Reply )
  1. Arrow
    Gravatar

    Your Name
    November 18th