codeigniter

Easy Reverse Routing with CodeIgniter


Easy Reverse Routing with CodeIgniter

By Kenny Katzgrau | Published: September 21, 2010

I really can’t stand hard-coding URLs in the views or controllers of my application — and I’m sure most other people can’t either. Here’s an extension for the CodeIgniter Router class that I wrote that gives you a nice way to write routes that are reversible and also have the ability to take parameters.

<?php

class MY_Router extends CI_Router
{
    private $_reverseRoutes = NULL;

    CONST ARR_ROUTE_POS      = 0;
    CONST ARR_ROUTE_NAME_POS = 1;

    function _parse_routes()
    {
		// Do we even have any custom routing to deal with?
		// There is a default scaffolding trigger, so we'll look just for 1
		if (count($this->routes) == 1)
		{
			$this->_set_request($this->uri->segments);
			return;
		}

		// Turn the segment array into a URI string
		$uri = implode('/', $this->uri->segments);

		// Is there a literal match?  If so we're done
		if (isset($this->routes[$uri]))
		{
			$this->_set_request(explode('/', $this->routes[$uri][self::ARR_ROUTE_POS]));
			return;
		}

		// Loop through the route array looking for wild-cards
		foreach ($this->routes as $key => $val)
		{
			// Convert wild-cards to RegEx
            //echo "$key --> ";
			$key = preg_replace('/\:\w+/', '[\w\-_]+', $key);
            //echo "$key <br />";
			// Does the RegEx match?
			if (preg_match('#^'.$key.'$#', $uri))
			{
				// Do we have a back-reference?
				if (strpos($val[self::ARR_ROUTE_POS], '$') !== FALSE AND strpos($key, '(') !== FALSE)
				{
					$val = preg_replace('#^'.$key.'$#', $val[self::ARR_ROUTE_POS], $uri);   
				}

				$this->_set_request(explode('/', $val));
				return;
			}
		}

		// If we got this far it means we didn't encounter a
		// matching route so we'll set the site default route
		$this->_set_request($this->uri->segments);
    }

    function _buildReverseRoutes()
    {
        $reverse_routes = array();

        foreach($this->routes as $route => $info)
        {
            # If this is a default route or scaffolding key, ignore it
            if(!is_array($info)) continue;

            $name = $info[self::ARR_ROUTE_NAME_POS];
            $reverse_routes[$name] = $route;
        }

        $this->_reverseRoutes = & $reverse_routes;
    }

    function reverseRoute($route_name, $args_keyval = array())
    {
        if($this->_reverseRoutes === NULL)
            $this->_buildReverseRoutes();

        if(!array_key_exists($route_name, $this->_reverseRoutes))
            show_error("No reverse route found for '$route_name'");

        $route = $this->_reverseRoutes[$route_name];

        foreach($args_keyval as $key => $val)
        {
            $route = str_replace("(:$key)", $val, $route);
        }

        return $route;
    }
}

Drop that into application/libraries, then rewrite your routes to look like this:

$route['users/(:username)']  = array('users/$1', 'user-homepage');
$route['companies/(:slug)']  = array('companies/$1', 'company-homepage');

Let me explain that.

CodeIgniter lets you use wildcards in your routes like (:any) or (:num). That’s no more with this extension. Basically, anything you put in (:[name]) format with be treated like (:any). That’s handy, and I’ll tell you why.

Once you rewrite you routes, you can now call a new method on the routing class when you need to, say, redirect the user to his homepage after login:

  # login was successful, and we now have a $user object
  $this->load->helper('url');
  redirect($this->router->reverseRoute('user-homepage', array('username' => $user->username));

The reverseRoute method takes two parameters: The route you want to send the use on, and any wildcards that you need to fill in the url. For the user-homepage route, there is a (:username) wildcard in the route. We can pass the appropriate fill-in for that wilcard with the second parameter with an associative key-value array.

A redirect to a company-homepage would look like:

  # ...
  redirect($this->router->reverseRoute('company-homepage', array('slug' => $company->slug));

Then in the future, if you feel like changing your routes, go no further than the routes file! Mucking around in views is a recipe for broken links.

 

source:

http://codefury.net/2010/09/easy-reverse-routing-with-codeigniter/

 

Advertisements

1 thought on “Easy Reverse Routing with CodeIgniter”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s