Many of you SEO fanatics may have realized that CodeIgniter is not very SEO-friendly out of the box. It auto generates URLs based on routes which are made up of a controller name and method name. For URLs to be considered SEO-friendly and be universally recognized by search engines, keywords must be separated by a dash. Many of you are thinking you will just go rename your controllers and methods with dashes. That would be nice and easy, but this is not a legal syntax and PHP will throw errors. There is the option to manually enter each route in your routes.php file, but this could be a serious beat down and come back to haunt you later on down the road. Here is a quick guide to get your CodeIgniter 2.0 + HMVC (Modular Extensions) setup supporting SEO friendly URLs: Because of the way CodeIgniter functions, you will not have to make any changes to your CodeIgniter or HMVC core files. When you installed HMVC you should have added a MY_Router.php file to the /application/core/ directory. By replacing that file with the following code you should now be able to reference controllers and methods with dashes. For example a controller with the name my_controller can can now be referenced as my-controller in your URL.

<?php (defined('BASEPATH')) OR exit('No direct script access allowed');
// load the MX_Router class
require APPPATH."third_party/MX/Router.php";                                                                             

class MY_Router extends MX_Router {                                                                                      

    private $module;                                                                                                     

    public function fetch_module() {
        return $this->module;
    }                                                                                                           

    public function _validate_request($segments) {                                                                       

        /* locate module controller */
        if ($located = $this->locate($segments)) return $located;                                                        

        /* use a default 404 controller */
        if (isset($this->routes['404']) AND $segments = explode('/', $this->routes['404'])) {
            if ($located = $this->locate($segments)) return $located;
        }                                                                                                                

        /* use a default 404_override controller CI 2.0 */
        if (isset($this->routes['404_override']) AND $segments = explode('/', $this->routes['404_override'])) {
            if ($located = $this->locate($segments)) return $located;
        }                                                                                                                

        /* no controller found */
        show_404();
    }                                                                                                                    

    /** Locate the controller **/
    public function locate($segments) {                                                                                  

        $this->module = '';
        $this->directory = '';
        $ext = $this->config->item('controller_suffix').EXT;                                                             

        /* use module route if available */
        if (isset($segments[0]) AND $routes = Modules::parse_routes($segments[0], implode('/', $segments)) {
            $segments = $routes;
        }                                                                                                                

        /* get the segments array elements */
        list($module, $directory, $controller) = array_pad($segments, 3, NULL);                                          

        $module = str_replace('-', '_', $module);                                                                                                                                                                                

        $controller = str_replace('-', '_', $controller);                                                                                                    

        $directory = str_replace('-', '_', $directory);                                                                  

        foreach (Modules::$locations as $location => $offset) {                                                          

            /* module exists? */
            if (is_dir($source = $location.$module.'/controllers/')) {                                                   

                $this->module = $module;
                $this->directory = $offset.$module.'/controllers/';                                                      

                /* module sub-controller exists? */
                if($directory AND is_file($source.$directory.$ext)) {
                    return array_slice($segments, 1);
                }                                                                                                        

                /* module sub-directory exists? */
                if($directory AND is_dir($module_subdir = $source.$directory.'/')) {                                     

                    $this->directory .= $directory.'/';                                                                  

                    /* module sub-directory controller exists? */
                    if(is_file($module_subdir.$directory.$ext)) {
                        return array_slice($segments, 1);
                    }                                                                                                    

                    /* module sub-directory sub-controller exists? */
                    if($controller AND is_file($module_subdir.$controller.$ext))    {
                        return array_slice($segments, 2);
                    }
                }                                                                                                        

                /* module controller exists? */
                if(is_file($source.$module.$ext)) {
                    return $segments;
                }
            }
        }                                                                                                                

        /* application controller exists? */
        if(is_file(APPPATH.'controllers/'.$module.$ext)) {
            return $segments;
        }                                                                                                                

        /* application sub-directory controller exists? */
        if(is_file(APPPATH.'controllers/'.$module.'/'.$directory.$ext)) {
            $this->directory = $module.'/';
            return array_slice($segments, 1);
        }                                                                                                                

        /* application sub-directory default controller exists? */
        if(is_file(APPPATH.'controllers/'.$module.'/'.$this->default_controller.$ext)) {
            $this->directory = $module.'/';
            return array($this->default_controller);
        }
    }                                                                                                                 

    public function set_class($class)
    {
        $this->class = str_replace('-', '_', $this->class).$this->config->item('controller_suffix');
    }                                                                                                                 

    public function set_method($method)
    {
        $this->method = str_replace('-', '_', $this->method);
    }
}
Mark Price

Posted by Mark Price

About Mark Price

View all posts by Mark Price