Modules

Route
extends Kohana_Route

Routes are used to determine the controller and action for a requested URI. Every route generates a regular expression which is used to match a URI and a route. Routes may also contain keys which can be used to set the controller, action, and parameters.

Each will be translated to a regular expression using a default regular expression pattern. You can override the default pattern by providing a pattern for the key:

// This route will only match when <id> is a digit
Route::set('user', 'user/<action>/<id>', array('id' => '\d+'));
 
// This route will match when <path> is anything
Route::set('file', '<path>', array('path' => '.*'));

It is also possible to create optional segments by using parentheses in the URI definition:

// This is the standard default route, and no keys are required
Route::set('default', '(<controller>(/<action>(/<id>)))');
 
// This route only requires the <file> key
Route::set('file', '(<path>/)<file>(.<format>)', array('path' => '.*', 'format' => '\w+'));

Routes also provide a way to generate URIs (called "reverse routing"), which makes them an extremely powerful and flexible way to generate internal links.

package
Kohana
category
Base
author
Kohana Team
copyright
© 2008-2012 Kohana Team
license
http://kohanaframework.org/license

Class declared in SYSPATH/classes/Route.php on line 3.

Constants

REGEX_GROUP

string(26) "\(((?:(?>[^()]+)|(?R))*)\)"

REGEX_KEY

string(18) "<([a-zA-Z0-9_]++)>"

REGEX_SEGMENT

string(12) "[^/.,;?\n]++"

REGEX_ESCAPE

string(17) "[.\+*?[^\]${}=!|]"

Properties

public static bool $cache

Indicates whether routes are cached

bool FALSE

public static string $default_action

default action for all routes

string(5) "index"

public static string $default_protocol

default protocol for all routes

string(7) "http://"

public static array $localhosts

list of valid localhost entries

array(4) (
    0 => bool FALSE
    1 => string(0) ""
    2 => string(5) "local"
    3 => string(9) "localhost"
)

protected array $_defaults

Default value:
array(2) (
    "action" => string(5) "index"
    "host" => bool FALSE
)

protected array $_filters

route filters

Default value:
array(0) 

protected array $_regex

Default value:
array(0) 

protected string $_route_regex

Default value:
NULL

protected static array $_routes

array(5) (
    "codebench" => object Route(5) {
        protected _filters => array(0) 
        protected _uri => string(19) "codebench(/<class>)"
        protected _regex => array(0) 
        protected _defaults => array(3) (
            "controller" => string(9) "Codebench"
            "action" => string(5) "index"
            "class" => NULL
        )
        protected _route_regex => string(44) "#^codebench(?:/(?P<class>[^/.,;?\n]++))?$#uD"
    }
    "docs/media" => object Route(5) {
        protected _filters => array(0) 
        protected _uri => string(20) "guide-media(/<file>)"
        protected _regex => array(1) (
            "file" => string(2) ".+"
        )
        protected _defaults => array(3) (
            "controller" => string(9) "Userguide"
            "action" => string(5) "media"
            "file" => NULL
        )
        protected _route_regex => string(35) "#^guide-media(?:/(?P<file>.+))?$#uD"
    }
    "docs/api" => object Route(5) {
        protected _filters => array(0) 
        protected _uri => string(19) "guide-api(/<class>)"
        protected _regex => array(1) (
            "class" => string(13) "[a-zA-Z0-9_]+"
        )
        protected _defaults => array(3) (
            "controller" => string(9) "Userguide"
            "action" => string(3) "api"
            "class" => NULL
        )
        protected _route_regex => string(45) "#^guide-api(?:/(?P<class>[a-zA-Z0-9_]+))?$#uD"
    }
    "docs/guide" => object Route(5) {
        protected _filters => array(0) 
        protected _uri => string(25) "guide(/<module>(/<page>))"
        protected _regex => array(1) (
            "page" => string(2) ".+"
        )
        protected _defaults => array(3) (
            "controller" => string(9) "Userguide"
            "action" => string(4) "docs"
            "module" => string(0) ""
        )
        protected _route_regex => string(59) "#^guide(?:/(?P<module>[^/.,;?\n]++)(?:/(?P<page>.+))?)?$#uD"
    }
    "default" => object Route(5) {
        protected _filters => array(0) 
        protected _uri => string(32) "(<controller>(/<action>(/<id>)))"
        protected _regex => array(0) 
        protected _defaults => array(2) (
            "controller" => string(7) "welcome"
            "action" => string(5) "index"
        )
        protected _route_regex => string(95) "#^(?:(?P<controller>[^/.,;?\n]++)(?:/(?P<action>[^/.,;?\n]++)(?:/(?P<id>[^/.,;?\n]++))?)?)?$#uD"
    }
)

protected string $_uri

route URI

Default value:
string(0) ""

Methods

public __construct( [ string $uri = NULL , array $regex = NULL ] ) (defined in Kohana_Route)

Creates a new route. Sets the URI and regular expressions for keys. Routes should always be created with Route::set or they will not be properly stored.

$route = new Route($uri, $regex);

The $uri parameter should be a string for basic regex matching.

Parameters

  • string $uri = NULL - Route URI pattern
  • array $regex = NULL - Key patterns

Tags

Return Values

  • void

Source Code

public function __construct($uri = NULL, $regex = NULL)
{
    if ($uri === NULL)
    {
        // Assume the route is from cache
        return;
    }
 
    if ( ! empty($uri))
    {
        $this->_uri = $uri;
    }
 
    if ( ! empty($regex))
    {
        $this->_regex = $regex;
    }
 
    // Store the compiled regex locally
    $this->_route_regex = Route::compile($uri, $regex);
}

public static all( ) (defined in Kohana_Route)

Retrieves all named routes.

$routes = Route::all();

Return Values

  • array - Routes by name

Source Code

public static function all()
{
    return Route::$_routes;
}

public static cache( [ boolean $save = bool FALSE , boolean $append = bool FALSE ] ) (defined in Kohana_Route)

Saves or loads the route cache. If your routes will remain the same for a long period of time, use this to reload the routes from the cache rather than redefining them on every page load.

if ( ! Route::cache())
{
    // Set routes here
    Route::cache(TRUE);
}

Parameters

  • boolean $save = bool FALSE - Cache the current routes
  • boolean $append = bool FALSE - Append, rather than replace, cached routes when loading

Tags

Return Values

  • void - When saving routes
  • boolean - When loading routes

Source Code

public static function cache($save = FALSE, $append = FALSE)
{
    if ($save === TRUE)
    {
        try
        {
            // Cache all defined routes
            Kohana::cache('Route::cache()', Route::$_routes);
        }
        catch (Exception $e)
        {
            // We most likely have a lambda in a route, which cannot be cached
            throw new Kohana_Exception('One or more routes could not be cached (:message)', array(
                    ':message' => $e->getMessage(),
                ), 0, $e);
        }
    }
    else
    {
        if ($routes = Kohana::cache('Route::cache()'))
        {
            if ($append)
            {
                // Append cached routes
                Route::$_routes += $routes;
            }
            else
            {
                // Replace existing routes
                Route::$_routes = $routes;
            }
 
            // Routes were cached
            return Route::$cache = TRUE;
        }
        else
        {
            // Routes were not cached
            return Route::$cache = FALSE;
        }
    }
}

public static compile( ) (defined in Kohana_Route)

Returns the compiled regular expression for the route. This translates keys and optional groups to a proper PCRE regular expression.

$compiled = Route::compile(
   '<controller>(/<action>(/<id>))',
    array(
      'controller' => '[a-z]+',
      'id' => '\d+',
    )
);

Tags

Return Values

  • string

Source Code

public static function compile($uri, array $regex = NULL)
{
    // The URI should be considered literal except for keys and optional parts
    // Escape everything preg_quote would escape except for : ( ) < >
    $expression = preg_replace('#'.Route::REGEX_ESCAPE.'#', '\\\\$0', $uri);
 
    if (strpos($expression, '(') !== FALSE)
    {
        // Make optional parts of the URI non-capturing and optional
        $expression = str_replace(array('(', ')'), array('(?:', ')?'), $expression);
    }
 
    // Insert default regex for keys
    $expression = str_replace(array('<', '>'), array('(?P<', '>'.Route::REGEX_SEGMENT.')'), $expression);
 
    if ($regex)
    {
        $search = $replace = array();
        foreach ($regex as $key => $value)
        {
            $search[]  = "<$key>".Route::REGEX_SEGMENT;
            $replace[] = "<$key>$value";
        }
 
        // Replace the default regex with the user-specified regex
        $expression = str_replace($search, $replace, $expression);
    }
 
    return '#^'.$expression.'$#uD';
}

public defaults( [ array $defaults = NULL ] ) (defined in Kohana_Route)

Provides default values for keys when they are not present. The default action will always be "index" unless it is overloaded here.

$route->defaults(array(
    'controller' => 'welcome',
    'action'     => 'index'
));

If no parameter is passed, this method will act as a getter.

Parameters

  • array $defaults = NULL - Key values

Return Values

  • $this - Or array

Source Code

public function defaults(array $defaults = NULL)
{
    if ($defaults === NULL)
    {
        return $this->_defaults;
    }
 
    $this->_defaults = $defaults;
 
    return $this;
}

public filter( array $callback ) (defined in Kohana_Route)

Filters to be run before route parameters are returned:

$route->filter(
    function(Route $route, $params, Request $request)
    {
        if ($request->method() !== HTTP_Request::POST)
        {
            return FALSE; // This route only matches POST requests
        }
        if ($params AND $params['controller'] === 'welcome')
        {
            $params['controller'] = 'home';
        }
 
        return $params;
    }
);

To prevent a route from matching, return FALSE. To replace the route parameters, return an array.

Default parameters are added before filters are called!

Parameters

  • array $callback required - Callback string, array, or closure

Tags

Return Values

  • $this

Source Code

public function filter($callback)
{
    if ( ! is_callable($callback))
    {
        throw new Kohana_Exception('Invalid Route::callback specified');
    }
 
    $this->_filters[] = $callback;
 
    return $this;
}

public static get( string $name ) (defined in Kohana_Route)

Retrieves a named route.

$route = Route::get('default');

Parameters

  • string $name required - Route name

Tags

Return Values

  • Route

Source Code

public static function get($name)
{
    if ( ! isset(Route::$_routes[$name]))
    {
        throw new Kohana_Exception('The requested route does not exist: :route',
            array(':route' => $name));
    }
 
    return Route::$_routes[$name];
}

public is_external( ) (defined in Kohana_Route)

Returns whether this route is an external route to a remote controller.

Return Values

  • boolean

Source Code

public function is_external()
{
    return ! in_array(Arr::get($this->_defaults, 'host', FALSE), Route::$localhosts);
}

public matches( Request $request ) (defined in Kohana_Route)

Tests if the route matches a given Request. A successful match will return all of the routed parameters as an array. A failed match will return boolean FALSE.

// Params: controller = users, action = edit, id = 10
$params = $route->matches(Request::factory('users/edit/10'));

This method should almost always be used within an if/else block:

if ($params = $route->matches($request))
{
    // Parse the parameters
}

Parameters

  • Request $request required - Request object to match

Return Values

  • array - On success
  • FALSE - On failure

Source Code

public function matches(Request $request)
{
    // Get the URI from the Request
    $uri = trim($request->uri(), '/');
 
    if ( ! preg_match($this->_route_regex, $uri, $matches))
        return FALSE;
 
    $params = array();
    foreach ($matches as $key => $value)
    {
        if (is_int($key))
        {
            // Skip all unnamed keys
            continue;
        }
 
        // Set the value for all matched keys
        $params[$key] = $value;
    }
 
    foreach ($this->_defaults as $key => $value)
    {
        if ( ! isset($params[$key]) OR $params[$key] === '')
        {
            // Set default values for any key that was not matched
            $params[$key] = $value;
        }
    }
 
    if ( ! empty($params['controller']))
    {
        // PSR-0: Replace underscores with spaces, run ucwords, then replace underscore
        $params['controller'] = str_replace(' ', '_', ucwords(str_replace('_', ' ', $params['controller'])));
    }
 
    if ( ! empty($params['directory']))
    {
        // PSR-0: Replace underscores with spaces, run ucwords, then replace underscore
        $params['directory'] = str_replace(' ', '_', ucwords(str_replace('_', ' ', $params['directory'])));
    }
 
    if ($this->_filters)
    {
        foreach ($this->_filters as $callback)
        {
            // Execute the filter giving it the route, params, and request
            $return = call_user_func($callback, $this, $params, $request);
 
            if ($return === FALSE)
            {
                // Filter has aborted the match
                return FALSE;
            }
            elseif (is_array($return))
            {
                // Filter has modified the parameters
                $params = $return;
            }
        }
    }
 
    return $params;
}

public static name( Route $route ) (defined in Kohana_Route)

Get the name of a route.

$name = Route::name($route)

Parameters

  • Route $route required - Instance

Return Values

  • string

Source Code

public static function name(Route $route)
{
    return array_search($route, Route::$_routes);
}

public static set( string $name [, string $uri = NULL , array $regex = NULL ] ) (defined in Kohana_Route)

Stores a named route and returns it. The "action" will always be set to "index" if it is not defined.

Route::set('default', '(<controller>(/<action>(/<id>)))')
    ->defaults(array(
        'controller' => 'welcome',
    ));

Parameters

  • string $name required - Route name
  • string $uri = NULL - URI pattern
  • array $regex = NULL - Regex patterns for route keys

Return Values

  • Route

Source Code

public static function set($name, $uri = NULL, $regex = NULL)
{
    return Route::$_routes[$name] = new Route($uri, $regex);
}

public uri( [ array $params = NULL ] ) (defined in Kohana_Route)

Generates a URI for the current route based on the parameters given.

// Using the "default" route: "users/profile/10"
$route->uri(array(
    'controller' => 'users',
    'action'     => 'profile',
    'id'         => '10'
));

Parameters

  • array $params = NULL - URI parameters

Tags

Return Values

  • string

Source Code

public function uri(array $params = NULL)
{
    if ($params)
    {
        // @issue #4079 rawurlencode parameters
        $params = array_map('rawurlencode', $params);
        // decode slashes back, see Apache docs about AllowEncodedSlashes and AcceptPathInfo
        $params = str_replace(array('%2F', '%5C'), array('/', '\\'), $params);
    }
 
    $defaults = $this->_defaults;
 
    /**
     * Recursively compiles a portion of a URI specification by replacing
     * the specified parameters and any optional parameters that are needed.
     *
     * @param   string  $portion    Part of the URI specification
     * @param   boolean $required   Whether or not parameters are required (initially)
     * @return  array   Tuple of the compiled portion and whether or not it contained specified parameters
     */
    $compile = function ($portion, $required) use (&$compile, $defaults, $params)
    {
        $missing = array();
 
        $pattern = '#(?:'.Route::REGEX_KEY.'|'.Route::REGEX_GROUP.')#';
        $result = preg_replace_callback($pattern, function ($matches) use (&$compile, $defaults, &$missing, $params, &$required)
        {
            if ($matches[0][0] === '<')
            {
                // Parameter, unwrapped
                $param = $matches[1];
 
                if (isset($params[$param]))
                {
                    // This portion is required when a specified
                    // parameter does not match the default
                    $required = ($required OR ! isset($defaults[$param]) OR $params[$param] !== $defaults[$param]);
 
                    // Add specified parameter to this result
                    return $params[$param];
                }
 
                // Add default parameter to this result
                if (isset($defaults[$param]))
                    return $defaults[$param];
 
                // This portion is missing a parameter
                $missing[] = $param;
            }
            else
            {
                // Group, unwrapped
                $result = $compile($matches[2], FALSE);
 
                if ($result[1])
                {
                    // This portion is required when it contains a group
                    // that is required
                    $required = TRUE;
 
                    // Add required groups to this result
                    return $result[0];
                }
 
                // Do not add optional groups to this result
            }
        }, $portion);
 
        if ($required AND $missing)
        {
            throw new Kohana_Exception(
                'Required route parameter not passed: :param',
                array(':param' => reset($missing))
            );
        }
 
        return array($result, $required);
    };
 
    list($uri) = $compile($this->_uri, TRUE);
 
    // Trim all extra slashes from the URI
    $uri = preg_replace('#//+#', '/', rtrim($uri, '/'));
 
    if ($this->is_external())
    {
        // Need to add the host to the URI
        $host = $this->_defaults['host'];
 
        if (strpos($host, '://') === FALSE)
        {
            // Use the default defined protocol
            $host = Route::$default_protocol.$host;
        }
 
        // Clean up the host and prepend it to the URI
        $uri = rtrim($host, '/').'/'.$uri;
    }
 
    return $uri;
}

public static url( string $name [, array $params = NULL , mixed $protocol = NULL ] ) (defined in Kohana_Route)

Create a URL from a route name. This is a shortcut for:

echo URL::site(Route::get($name)->uri($params), $protocol);

Parameters

  • string $name required - Route name
  • array $params = NULL - URI parameters
  • mixed $protocol = NULL - Protocol string or boolean, adds protocol and domain

Tags

Return Values

  • string

Source Code

public static function url($name, array $params = NULL, $protocol = NULL)
{
    $route = Route::get($name);
 
    // Create a URI with the route and convert it to a URL
    if ($route->is_external())
        return $route->uri($params);
    else
        return URL::site($route->uri($params), $protocol);
}