Skip to content

routing

Lode Claassen edited this page Apr 27, 2016 · 8 revisions

By default, you don't need to fiddle with routing. But if you want, you can use whatever structure you want.

Basics

Default mapping to controllers

Everything in the url path is mapped directly to a controller's file name. I.e. http://hostname/foo will require_once the application/controllers/foo.php file.

Note: this automatic mapping is fine for getting started, but you soon might need to Define custom routes. Also see the Remarks for some caveats.

Note: this will also auto instantiate a class with the same name, see Disable auto instantiation.

Define custom routes

Extend the get_custom_routes() method and return an array with custom routes. Also, set $map_to_filesystem to false.

Make a application/helpers/routing.php file with the following contents:

<?php

namespace projectname\helpers;
use alsvanzelf\fem;

class routing extends fem\routing {
	protected $map_to_filesystem = false;
	
	protected function get_custom_routes() {
		$routes = [];
		$routes['GET']['foo'] = 'foo';
		
		return $routes;
	}
}

Also, in your index.php, change new \alsvanzelf\fem\routing(); to new \projectname\routing();

This routes /foo to foo.php just as with Default mapping to controllers. However, now you can use friendlier and richer routes via regular expressions, name and structure the underlying file in whatever way suites your application, and only allow specific methods.

See Route to a method, Route to a closure, or example-rpoject/application/routing.php for more examples.

Extras

Route to a method

If you Defined custom routes, use the method notation (class->method):

$routes['GET']['foo'] = '\projectname\foo->bar';

to instantiate a class called \projectname\foo, and call the bar() method on it.

If you want to call a static method, use the static notation (class::function):

$routes['GET']['foo'] = '\projectname\foo::bar';

Note: always use fully qualified names for the class names.

Route to a closure

If you Defined custom routes, define a closure:

$routes['GET']['foo'] = function($url, $method, $arguments) { echo 'bar'; };

Route to a file

If you Defined custom routes, don't use -> or :: to execute a file:

$routes['GET']['foo'] = 'anything_goes';

Which will load anything_goes.php.

Note: this will also auto instantiate a class with the same name, see Disable auto instantiation.

Adjust default route

The default route (when you use an empty path in the url) is home. Adjust this by extending the class and setting $default_handler to the value you want.

Make a application/helpers/routing.php file with the following contents:

<?php

namespace projectname\helpers;
use alsvanzelf\fem;

class routing extends fem\routing {
	protected $default_handler = 'customclass->custom_method';
}

Also, in your index.php, change new \alsvanzelf\fem\routing(); to new \projectname\routing();

Note: the default route can not map to a closure without a bit more work.

Catch-all unmatched routes

If a route can not be matched, a 404 is presented. If you want to load the default handler instead, extend the class and set $fallback_to_default to true.

Make a application/helpers/routing.php file with the following contents:

<?php

namespace projectname\helpers;
use alsvanzelf\fem;

class routing extends fem\routing {
	protected $fallback_to_default = true;
}

Also, in your index.php, change new \alsvanzelf\fem\routing(); to new \projectname\routing();

Disable auto instantiation

When using the Default mapping to controllers, classes are auto instantiated. I.e. route /foo executes require_once foo.php; new foo($url, $method, $arguments);.

Disable auto instantiation by extending the class and setting $auto_instantiation to false.

Make a application/helpers/routing.php file with the following contents:

<?php

namespace projectname\helpers;
use alsvanzelf\fem;

class routing extends fem\routing {
	protected $auto_instantiation = false;
}

Also, in your index.php, change new \alsvanzelf\fem\routing(); to new \projectname\routing();

Set another base path instead of controllers

If you use Default mapping to controllers, and/or Route to a file, a route is handled by files in the controllers directory. If you want to use a different directory, i.e. application/viewmodels, extend the class and set $handler_base_path.

Make a application/helpers/routing.php file with the following contents:

<?php

namespace projectname\helpers;
use alsvanzelf\fem;

class routing extends fem\routing {
	protected $handler_base_path = 'viewmodels';
}

Also, in your index.php, change new \alsvanzelf\fem\routing(); to new \projectname\routing();

Syntax

Except for the constructor called by your index.php, no methods are public.

Most methods are protected and can be extended, see the various examples and the routing file itself.

Remarks

Allowed characters

In general, any character which a browser accepts is allowed as part of the route. However:

  • The Default mapping to controllers only allow alphanumeric characters, underscore, dash, and slash (a-zA-Z0-9/_-).
  • When you Defined custom routes, you'll need to escape certain characters as the route is seen as part of a regular expression ({^'.$route.'$}).

Passed arguments

Every handler (whether it's a file, method, or closure), gets passed three arguments from the request:

Argument Details
$url The path of the url, exclusing the leading slash. I.e. /foo/bar gives foo/bar. Also see [[fem\request::get_url()
$method The method used, one of GET, PUT, POST, PATCH, DELETE, OPTIONS, HEAD. Also see [[fem\request::get_method()
$arguments An array of variables from subpattern in the custom route regular expressions. I.e. a route order/(?<id>[0-9]+) gives array('id' => 42).

Note: query string arguments are just fetched via $_GET. POST data via $_POST or [[fem\request::get_data()
You can’t perform that action at this time.