Welcome Guest, Not a member yet? Register   Sign In
Database driven routes in CodeIgniter
#1

[eluser]neillyons.co[/eluser]
See updated version of this here

Using a pre_system hook the routes array can be populated from your database.

A route is a CodeIgniter controller action alias. Used to build search engine friendly sites. eg posts/database-driven-routes-in-codeigniter is mapped to posts/get/2

Step 1

Define the hook by inserting the code below into the hooks.php file ( ..system/application/config/hooks.php ).

Code:
require_once BASEPATH."application/config/database.php";

$hook['pre_system'] = array(
                                'class'    => 'Router_Hook',
                                'function' => 'get_routes',
                                'filename' => 'Router_Hook.php',
                                'filepath' => 'hooks',
                                'params'   => array(
                                    $db['default']['hostname'],
                                    $db['default']['username'],
                                    $db['default']['password'],
                                    $db['default']['database'],
                                    $db['default']['dbprefix'],
                                    )
                                );
This is a pre system hook, which means it is called before any routing has occurred. This hook will call the function get_routes with the database connection details passed as a paramater.

Step 2

Create a file called Router_Hook.php in the hooks directory ( ..system/application/hooks/Router_Hook.php ) and insert the code below.

Code:
if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Router_Hook
{
        /**
         * Loads routes from database.
         *
         * @access public
         * @params array : hostname, username, password, database, db_prefix
         * @return void
         */
    function get_routes($params)
    {
        global $DB_ROUTES;

        mysql_connect($params[0], $params[1], $params[2]);

        mysql_select_db($params[3]);

        $sql = "SELECT * FROM {$params[4]}routes";
        $query = mysql_query($sql);

        $routes = array();
        while ($route = mysql_fetch_array($query, MYSQL_ASSOC)) {
            $routes[$route['route']] = $route['controller'];
        }
        mysql_free_result($query);
        mysql_close();
        $DB_ROUTES = $routes;
    }
}
The database schema

Code:
id, route, controller, created, updated
This function populates a keyed array from the database and makes the array globally available.

Step 3

Insert the code below into the routes.php file ( ..system/application/configs/routes.php ) after the scaffolding trigger.

Code:
global $DB_ROUTES;
if(!empty($DB_ROUTES)) $route = array_merge($route,$DB_ROUTES);
This code merges the array populated from the database with the array defined in the routes.php file.

Step 4

In the config.php file ( ..system/application/configs/config.php ) set enable hooks to TRUE.

Code:
$config['enable_hooks'] = TRUE;
Now when CodeIgniter is routing a request it will consider the routes from the database.


This technique will work as it is, but I recommend using DataMapper to save routes to the database aswell. Below is my route datamapper model.


Code:
class Route extends DataMapper
{
    var $validation = array(
        array(
            'field' => 'route',
            'label' => 'URL alias',
            'rules' => array('required', 'trim', 'unique', 'min_length' => 3, 'max_length' => 255, 'reserved_word', 'dash_url', 'alpha_slash_dot')
        ),
        array(
            'field' => 'controller',
            'label' => 'Controller URL',
            'rules' => array('required')
        )
    );


    /**
     * Constructor
     */
    function __construct()
    {
        parent::__construct();
    }


    /**
     * Validation function. Checks field value isn't a controller name.
     *
     * @access private
     * @param  string : field name
     * @return bool
     */
    function _reserved_word($field)
    {
        $controller = array();

        $this->load->helper('directory');

        $map = directory_map(BASEPATH."application/controllers");

        foreach ($map as $value)
        {

                $filename_array = explode(".", $value);
                if ($filename_array[1] == EXT)
                {

                    //If file extension is php then store filename in array.
                    $controller[] = $filename_array[0];
                }
        }

        if (in_array($this->{$field}, $controller))
        {
            return FALSE;
        }
        else
        {
            return TRUE;
        }
    }


    /**
     * Converts the route into a search engine friendly URL
     *
     * @access private
     * @param string : field value
     * @return void
     */
    function _dash_url($field)
    {
        $this->{$field} = dash($this->{$field});
    }
}
This provides a great way to check the route to be saved isn’t an existing controller name. Preventing routes with the same name pointing to different controller actions.


Insert the code below at the bottom of the inflector_helper.php file ( ..system/application/helpers/inflector_helper.php )

Code:
/**
* Dash
*
* Takes multiple words separated by spaces and dashes them
*
* @access    public
* @param    string
* @return    str
*/
if ( ! function_exists('dash'))
{
    function dash($str)
    {
        return preg_replace('/[\s_]+/', '-', strtolower(trim($str)));
    }
}
This function is called when saving the route to the database. eg. paGe/HELLO WORLD to page/hello-world.

Let me know what you think of this feature.


Messages In This Thread
Database driven routes in CodeIgniter - by El Forum - 06-28-2009, 10:04 AM
Database driven routes in CodeIgniter - by El Forum - 07-01-2009, 11:42 AM
Database driven routes in CodeIgniter - by El Forum - 07-01-2009, 12:00 PM
Database driven routes in CodeIgniter - by El Forum - 07-01-2009, 12:32 PM
Database driven routes in CodeIgniter - by El Forum - 07-01-2009, 01:41 PM
Database driven routes in CodeIgniter - by El Forum - 07-03-2009, 02:41 PM
Database driven routes in CodeIgniter - by El Forum - 07-03-2009, 03:36 PM
Database driven routes in CodeIgniter - by El Forum - 01-25-2010, 06:30 PM
Database driven routes in CodeIgniter - by El Forum - 02-21-2010, 04:22 AM
Database driven routes in CodeIgniter - by El Forum - 05-15-2010, 04:01 AM
Database driven routes in CodeIgniter - by El Forum - 05-15-2010, 06:29 AM
Database driven routes in CodeIgniter - by El Forum - 05-19-2010, 01:40 PM
Database driven routes in CodeIgniter - by El Forum - 05-20-2010, 02:42 AM



Theme © iAndrew 2016 - Forum software by © MyBB