Skip to content


Subversion checkout URL

You can clone with
Download ZIP

DrF Reverse Routing

Derek Jones edited this page · 29 revisions
Clone this wiki locally

DrF Reverse Routing is an extension of the URL Helper that overrides the site_url function to provide a reverse lookup. If a custom route can be found that matches the given "standard CodeIgniter URI", a custom route URI will be created and returned. Otherwise, a standard site_url will be returned.

Discuss this in the Forum


  • Translates a "standard CodeIgniter URI" into a custom route if possible. Standard, in this case, means controller/function/param1/param2/.../paramN
  • Fails gracefully, providing a standard site_url if no route can be found/translated
  • Works automatically with all of URL Helper's functions
  • Concept inspired by CakePHP's reverse routing


  • place MY_url_helper.php in your system/application/helpers folder
  • include the URL helper in your controller ```php $this->load->helper( 'url' );
- use URL Helper's functions as you normally would

## Example

- setup a Test Controller

class Test extends Controller{

    function Test()

    function testFunc( $param1 ){
        echo 'You passed in: ' . $param1;

    function redirect()
        $this->load->helper( 'url' );
        redirect( 'test/testFunc/bar' );


  • create a route for the test function

$route['foo/(:any)'] = 'test/testFunc/$1';



2009.03.31 by AJ Heller Fixed a bug that did not handle unordered backreferences correctly (when $2 comes before $1, for example. Bug reported by Johan André View original report



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

 * DrF Reverse Routing
 * @author        AJ Heller <>
 * @link

// ------------------------------------------------------------------------

 * (Reverse) Site_URL
 * Returns a custom routed URL if one exists.  Returns a normal site_url otherwise.
 * It works by translating the passed-in URI into a custom route URI, if possible.
 * This function does not handle ANY regex used without capture-groups and back-references.
 * Visit to learn why
 * @access    public
 * @param    $uri    The standard CI URL, e.g. controller/function/param1
 * @param    $method
 * @param    $http_response_code

    function site_url($uri = '')

        $Router =& load_class('Router');

        // $uri is expected to be a string, in the form of controller/function/param1
        // trim leading and trailing slashes, just in case
        $uri = trim($uri,'/');

        $routes = $Router->routes;
        $reverseRoutes = array_flip( $routes );

        unset( $routes['default_controller'], $routes['scaffolding_trigger'] );

        // Loop through all routes to check for back-references, then see if the user-supplied URI matches one 
        foreach ($routes as $key => $val)

            // bailing if route contains ungrouped regex, otherwise this fails badly
            if( preg_match( '/[^\(][.+?{\:]/', $key ) )

            // Do we have a back-reference?
            if (strpos($val, '$') !== FALSE AND strpos($key, '(') !== FALSE)

                // Find all back-references in custom route and CI route 
                preg_match_all( '/\(.+?\)/', $key, $keyRefs );
                preg_match_all( '/\$.+?/', $val, $valRefs );

                $keyRefs = $keyRefs[0];

                // Create URI Regex, to test passed-in uri against a custom route's CI ( standard ) route
                $uriRegex = $val;

                // Extract positional parameters (backreferences), and order them such that
                // the keys of $goodValRefs dirrectly mirror the correct value in $keyRefs
                $goodValRefs = array();
                foreach ($valRefs[0] as $ref) {
                    $tempKey = substr($ref, 1);
                    if (is_numeric($tempKey)) {
                        $goodValRefs[$tempKey] = $ref;

                // Replaces back-references in CI route with custom route's regex [ $1 replaced with (:num), for example ]
                foreach ($goodValRefs as $tempKey => $ref) {
                    if (isset($keyRefs[$tempKey])) {
                        $uriRegex = str_replace($ref, $keyRefs[$tempKey], $uriRegex);

                // replace :any and :num with .+ and [0-9]+, respectively
                $uriRegex = str_replace(':any', '.+', str_replace(':num', '[0-9]+', $uriRegex));

                // regex creation is finished.  Test it against uri
                if (preg_match('#^'.$uriRegex.'$#', $uri)){
                    // A match was found.  We can now build the custom URI

                    // We need to create a custom route back-referenced regex, to plug user's uri params into the new routed uri.
                    // First, find all custom route strings between capture groups
                    $key = str_replace(':any', '.+', str_replace(':num', '[0-9]+', $key));

                    $routeString = preg_split( '/\(.+?\)/', $key );

                    // build regex using original CI route's back-references
                    $replacement = '';
                    $rsEnd = count( $routeString ) - 1;

                    // merge route strings with original back-references, 1-for-1, like a zipper
                    for( $i = 0; $i < $rsEnd; $i++ ){
                        $replacement .= $routeString[$i] . $valRefs[0][$i];
                    $replacement .= $routeString[$rsEnd];

                             At this point,our variables are defined as:
                                $uriRegex:        regex to match against user-supplied URI
                                $replacement:    custom route regex, replacing capture-groups with back-references

                            All that's left to do is create the custom URI, and return the site_url
                    $customURI = preg_replace( '#^'.$uriRegex.'$#', $replacement, $uri );

                    return normal_site_url( $customURI );

            // If there is a literal match AND no back-references are setup, and we are done
            else if($val == $uri)

                return normal_site_url( $key );

        return normal_site_url( $uri );


    function normal_site_url($uri = '')


        $CI =& get_instance();

        return $CI->config->site_url($uri);


Something went wrong with that request. Please try again.