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); } }