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