Making Codeigniter clean URLs cleaner

Posted on the May 10th, 2010 under Codeigniter,Programming by Sukumar

Usually when working with codeigniter you come across the use case where you need to remove the extra “index” appearing in the URL for purposes ranging from shorter URLs to SEO.

For example,

Current URL style: http://example.com/controller/method/category1/category2/page-name
Target URL style: http://example.com/category1/category2/page-name.html


As you can see, the difference in the target URL is the absence of the controller name and the method name and the presence of the extension “.html”. Now, lets see how to achieve this and why the extra extension is required.

Below is my version of .htaccess.

RewriteEngine on

RewriteRule ^([a-z0-9_-]+)\.html$ index.php/page/$1 [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond $1 !^(index\.php|asset|robots\.txt)
RewriteRule ^(.*)$ index.php/$1 [L]

The line that is extra is 3 which redirects all the requests for “.html” files to the controller named “page”.

Now, lets look at the page controller which will handle these requests.

<?php if (!defined('BASEPATH')) exit('No direct script access allowed');

class Page extends Controller
    {

    function __construct()
    {
        parent::Controller();
    }

    function _remap()
    {
        $segment_count = $this->uri->total_segments();
        $segments = $this->uri->segment_array();

        if($segment_count == 0)
        {
            $this->data['title'] = 'UB Group Wines Division';
            $this->load->view('home', $this->data);
        }
        elseif($segment_count == 2) // Single page
        {
            $page_url = $segments[2];
            // Handle the page request
        }
        elseif($segment_count == 3) // Page with category
        {
            $category = $segments[2];
            $page_url = $segments[3];
            // Handle the category + page request
        }
    }
}

In this way you can have pages with smaller and cleaner URLs.

Tips:
1. You can use any extension you like. e.g; in case you have static HTML files to server, you can use the extension “.html” for static and “.htm” for non-static files.
2. You can have any number of URL stubs before the “.html” extension and you can access all these stubs in the controller.

Cons:
1. The URL needs an extra extension.
2. Only one controller per extension.

Do let me know what you think about this or if there is any way to improve on this.

Related posts:

  1. Codeigniter: Separating reads and writes for scaling MySQL Generally websites average a ratio of 9:1 or more for...

Tags: , , ,

15 Responses to 'Making Codeigniter clean URLs cleaner'

Subscribe to comments with RSS
  1. Ruben Müller said, on May 12th, 2010 at 4:08 am

    Why don’t you use the routes.php?
    http://codeigniter.com/user_guide/general/routing.html

  2. Bob said, on May 12th, 2010 at 8:31 am

    I’m wondering why you would want the extension (.html, .htm, .php, whatever). If you’re looking for shorter, cleaner URLs, why not:

    Current: http://example.com/controller/method/category1/category2/page-name
    Target : http://example.com/controller/method/category1/category2

    or to really chop it up:

    Target : http://example.com/category1/category2

    I suppose it makes a difference if your controller/method names are married to your site structure (i.e., http://example.com/products/view/cat1/cat2) or not (http://example.com/whichpage/displayproducts/cat1/cat2) but at least to the way I code, I’m not seeing the benefits of this method.

    Cheers,
    Bob

  3. Sukumar said, on May 13th, 2010 at 9:26 pm

    @Ruben

    Using routes is an option. But in order to get URLs like

    http://example.com/category1/category2/page-name

    without the controller name and the method name (‘index’ for example); the route would be (Please note that I haven’t tested this below route)

    $route['(:any)'] = "page/$1";
    

    Then you would be able to use any other controller since all the requests are routed to “page” controller.

    Do let me know if there is a better routing method I missed.

    @Bob

    The main reasons I didn’t want

    Target : http://example.com/controller/method/category1/category2

    is because my URLs would have looked like

    http://example.com/page/index/category1/category2

    AFAIK, google considers the URL segments to be more important the closer they are to the domain name.

    Yes,

    Target : http://example.com/category1/category2

    is quite possible and using routes at that. However, I think we wouldn’ t be able to use other controllers because of this (Unless we have some filter that checks for the existence of the controller and then the category). Using extensions helps to map a particular extension to a specific controller whithout affecting any other controllers.

    One of the main use cases I can think of is for a small blog similar to wordpress.

    Hope that makes sense :)

  4. Henry Weismann said, on May 25th, 2010 at 6:21 am

    How about:

    Current Url: http://example.com/controller-method/category1/category2
    OR
    Current Url: http://example.com/subfolder-controller-method/category1/category2

    is because my URLs would have looked like

    Target Url: http://example.com/index.php/controller/method/category1/category2
    OR
    Target Url: http://example.com/index.php/controller/method/index/category1/category2


    RewriteEngine on

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond $1 !^(index\.php|asset|robots\.txt)
    RewriteRule ^([^/.]+)-([^/.]+)-([^/.]+)/(.*)$ index.php/$1/$2/$3/$4 [L]

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond $1 !^(index\.php|asset|robots\.txt)
    RewriteRule ^([^/.]+)-([^/.]+)/(.*)$ index.php/$1/$2/$3 [L]

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond $1 !^(index\.php|asset|robots\.txt)
    RewriteRule ^(.*)$ index.php/$1 [L]

    Using Routes:

    $route['^([^/.]+)-([^/.]+)/(.*)'] = "$1/$2/$3";
    $route['^([^/.]+)-([^/.]+)-([^/.]+)/(.*)'] = "$1/$2/$3/$4";

    I have no idea if that will work as I just wrote it now. Feel free to test it.

  5. Henry Weismann said, on May 25th, 2010 at 6:35 am

    Should read:

    Target Url: http://example.com/index.php/controller/method/category1/category2
    OR
    Target Url: http://example.com/index.php/subfolder/controller/method/index/category1/category2

  6. Sukumar said, on May 25th, 2010 at 6:55 am

    @Henry,

    Your code looks good, but my aim is to remove the controller and the method name from the URL.

    Target URL style: http://example.com/category1/category2/page-name

    Your method is useful to merge the forward slashes in the URL.
    Useful code nevertheless, thanks!

  7. rezronam said, on July 15th, 2010 at 8:59 pm

    Hi, It’s not working for me, I tried to put the .htaccess, index.php is still there. Sorry I’m new to CI.

  8. Richard said, on August 23rd, 2010 at 2:41 am

    http://www.domain.com/title/How to 20 cook a rice/2

    How to remove the ‘title’ using .htaccess in the link above.

    It should be link like this http://www.domain.com/How to 20 cook a rice/2

  9. Richard said, on August 23rd, 2010 at 2:44 am

    I am using the codeigniter.

    The look like this

    $route['title/:any/:num'] = ‘page/title/$1/$2′;

    http://www.domain.com/title/How to 20 cook a rice/2
    I want to convert this link into
    http://www.domain.com/How to 20 cook a rice/2

    please help me guys.

  10. Richard said, on August 24th, 2010 at 2:17 am

    How to remove the controller/method for cleaner URL in codeIgniter.

    The original url is below
    http://www.mydomain.com/controllers/method/variable
    and I want my url look like this
    http://www.mydomain.com/variable
    or http://www.mydomain.com/friendly-url-description/5
    5 -> is key or id of the table, and the friendly-url-description is description of the value. please help guys.

  11. Haab said, on November 15th, 2010 at 3:06 pm

    Possible to create a Route which only display one slash in the site ?
    example: http://example.com/my-articletitle

    would be helpful if any of you can give me a little help .

    thanks

  12. aizuddinmanap said, on November 25th, 2010 at 7:57 pm

    @Haab : yes it possible.

  13. Sean said, on January 2nd, 2011 at 4:56 pm

    One problem I notice about CI Urls is how they look inside of google on your website snippet. They all include a ../ inside the URL… have you noticed this and do you have any idea how to remove that ../ it wastes space and is distracting…

    Thanks,

    Sean

  14. admin said, on January 3rd, 2011 at 11:52 am

    @Sean,

    I didn’t really get what you are referring to. You can check the usage of this code snippet on http://www.fourseasonsvineyards.com/

    As you can see there are no “../” in the URLs anywhere. Do let me know if I am missing something.

  15. fivefinger said, on May 17th, 2011 at 6:37 am

    Is there any way to remove only index after controller name.

    Now my url is: http://example.com/controller/index/params1/params2

    But target is : http://example.com/controller/params1/params2

    Please reply the solution

Leave a Reply
XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>