All the routes will be defined in the routes.php. sFire lets you listen to HTTP request based on a given URL. The request will be forwarded to the given module, controller and associated action. From a simple website with just a single page and url to a complete restful API; routes.php is the way to go.
sFire\Routing\Router lets you listen to HTTP request based on a given URL. To create a new route, you will have to decide which HTTP method the route should listen to.
In the example below we want to listen to the HTTP GET method (by using the get method of the Router instance) on the url 'customer/details'. The second parameter of the get method is the unique identifier for this specific route. Every route should contain its own unique identifier, for you to determine. You can use these identifiers to generate a variable URL in the view for example.
Router :: get('customer/details', 'customer.details');
You must give a module, controller and action. To find all modules, you can look in the "modules/" directory. The name of the controller and actions are without the postfixes. So CustomerController.php will be "Customer" and detailsAction will be "details":
Router :: get('customer/details', 'customer.details') -> module('App') -> controller('Customer') -> action('details');
If you want to listen to all HTTP methods or your application logic should handle it, you can use the any method.
Router :: any('url', 'identifier');
Below is a list of the existing HTTP methods:
Router :: get('url', 'identifier');
Router :: post('url', 'identifier');
Router :: delete('url', 'identifier');
Router :: put('url', 'identifier');
Router :: head('url', 'identifier');
Router :: connect('url', 'identifier');
Router :: options('url', 'identifier');
Router :: trace('url', 'identifier');
Router :: patch('url', 'identifier');
You can also group routes by calling the group method. This will allow you to set multiple options once for all the routes within the group. You can even group the groups. Pass a closure function to this method and use the injected route object to set new attributes within the new group.
Router :: module('App') -> group(function($route) {
$route -> controller('Error') -> viewable(false) -> group(function($route) {
//These routes will have the "App" as module, "error" as controller and "false" as viewable
$route -> any('403', '403') -> action('403');
$route -> any('404', '404') -> action('404');
});
//This route will have the "App" as module
$route -> get('', 'home.index') -> controller('Home') -> action('index');
});
When grouping routes, you can prefix routes with a given URL using the prefix method. This method accepts a regular expression String that will be prepended to the url set with one of the HTTP methods.
Router :: module('App') -> prefix('customer/') -> group(function($route) {
//The URL the route will listen to: "customer/overview"
$route -> get('overview', 'customer.overview') -> controller('Customer') -> action('overview');
//The URL the route will listen to: "customer/add"
$route -> any('add', 'customer.add') -> controller('Customer') -> action('add');
});
You can also prepend the prefix by setting the second parameter to Boolean true:
Router :: module('App') -> prefix('dashboard/') -> group(function($route) {
$route -> prefix('customer/', true) -> group(function($route) {
//The URL the route will listen to: "dasboard/customer/overview"
$route -> get('overview', 'customer.overview') -> controller('Customer') -> action('overview');
});
//Other routes
[...]
});
When the current URL is not matched to a defined route url, a 404 HTTP status code will be triggerd. In other words, the page could not be found. You can create multiple 404 error routes by calling the error method. This method accepts a HTTP status code (Integer) as first parameter and a unique identifier for that route as second parameter.
Router :: module('App') -> controller('Error') -> group(function($route) {
$route -> error(404, 'error.404-a') -> action('404a');
$route -> error(404, 'error.404-b') -> action('404b');
$route -> error(404, 'error.404-c') -> action('404c');
});
In this case you can redirect to a specific 404 route if a customer could not be found in the database for example. But if the URL does not match any route, sFire will look at the default 404 error route which is the first 404 error route you have set. In this case the route with "error.404-a" as identifier.
You can also set the third parameter to make another 404 error route the default:
$route -> error(404, 'error.404-a') -> action('404a');
//This will be the default 404 error route
$route -> error(404, 'error.404-b', true) -> action('404b');
By default the Routes URL matching will test a given url in non strict-mode. The route url "customer/details" will match "customer/details?foo=bar". If you want to disable this, you can turn on strict-mode by calling the strict method.
Router :: get('customer/details', 'customer.details') -> strict(true);
It's very easy to use variables in your URL's, for example a customer id. There are five predefined types you can use or you may create your own custom variable with regular expressions.
In the table below, you can see the predefined types.
| Name | Explanation |
|---|---|
| int | Will match only integer numbers (1, 3, 10, 520, etc) |
| float | Will match any number |
| boolean | Will match only "true", "false", "0" or "1" |
| string | Will match everything |
| alphanumeric | Will only match all numbers and letters a to z and A to Z |
Example:
//Will match the URL: "/customer/details/52"
Router :: get('customer/details/{int}', 'customer.details');
To make a variable optional, you may use the "?" symbol after the type:
//Matches the URL: "/customer/details" and "/customer/details/52"
Router :: get('customer/details/{int?}', 'customer.details');
You can create your own custom types to use witch will match a regular expression.
//Matches the URL: "/customer/details/5" but NOT "/customer/details/a"
Router :: get('customer/details/{id}', 'customer.details') -> where('id', '[0-9]+');
To set multiple wheres, you can give the custom types as an Array:
//Matches the URL: "/customer/details/5/bar"
Router :: get('customer/details/{id}/{foo}', 'customer.details') -> where(['id' => '[0-9]', 'foo' => 'bar']);
When grouping routes, you can set the third parameter to Boolean false, to overwrite previous uses. By default, sFire will merge all the wheres into one where.
Router :: where('id', '[0-9]') -> group(function($route) {
$route -> get('customer/add', 'customer.add') -> where('id', '[a-z]', false);
});
Middleware provide a convenient mechanism for filtering HTTP requests entering your application. For example, middleware that verifies the user of your application is authenticated. If the user is not authenticated, the middleware can redirect the user to the login screen. However, if the user is authenticated, the middleware will allow the request to proceed further into the application.
sFire lets you assign middleware classes to routes:
//Assign the Authenticate middleware to a single route
Router :: get('customer', 'customer.index') -> middleware('Authenticate');
//Assign the Cors and Authenticate middleware to a single route
Router :: get('customer', 'customer.index') -> middleware('Cors', 'Authenticate');
Note: The order of the given middleware is the order of middleware execution.
You may also group middleware:
Router :: middleware('Authenticate') -> group(function($route) {
$route -> get('customer', 'customer.index'); //This route will inherrit the Authenticate middleware
});
You can assign variables which can be retrieved in the Controller.
To assign variables to routes, you can use the assign method:
Router :: get('customer', 'customer.index') -> assign('foo', 'bar');
$this -> route() -> getParam('foo'); //Outputs "bar"
$this -> route() -> getParams(); //Outputs Array('foo' => 'bar')
You can also specify multiple variables by giving an Array:
Router :: get('customer', 'customer.index') -> assign(['foo' => 'bar', 'baz' => 'qux']);
When grouping routes, you can set the third parameter to Boolean false, to overwrite previous assigns. By default, sFire will merge all the assigns into one assign.
Router :: assign('foo', 'bar') -> group(function($route) {
$route -> get('customer', 'customer.index') -> assign('baz', 'qux', false);
});
Instead of defining duplicate variables for each different route, you can use the uses method to tell the route that it should use the variables of the given route identifier.
Router :: get('customer', 'customer.index') -> assign('foo', 'bar');
//Use the assigned variables of the "customer.index" route
Router :: get('customer/add', 'customer.add') -> uses('customer.index');
You can even set (or overwrite) more variables to combine multiple variables.
Router :: get('customer', 'customer.index') -> assign('foo', 'bar');
Router :: get('customer/add', 'customer.add') -> assign(['baz' => 'qux', 'fol' => 'peq']) -> uses('customer.index');
Router :: get('customer/add', 'customer.add') -> assign('quux', 'quuux') -> uses('customer.add');
//Assigned variables:
Array
(
[quux] => quuux
[baz] => qux
[fol] => peq
[foo] => bar
)
When grouping routes, you can set the second parameter to Boolean false, to overwrite previous uses. By default, sFire will merge all the uses into one use.
Router :: get('customer', 'customer.index') -> assign('foo', 'bar');
Router :: get('customer/add', 'customer.add') -> assign(['baz' => 'qux', 'fol' => 'peq']);
Router :: uses('customer.index') -> group(function($route) {
//This route will only use the variables from the "customer.add" route
$route -> get('customer/add', 'customer.add') -> uses('customer.add', false);
});
If you have routes that should not be accessible through the outside world (ie. browsers), you can mark routes as non viewable. This could be handy if you have a 403 Forbidden controller, but you don't want your users to navigate to this controller directly but do want to internal redirect (see the "Internal redirect" in Router.
You can set the viewable method to false:
Router :: any('403', '403') -> viewable(false);
If your application is listening to multiple domains, you may define a single route to one or multiple domains. This way, you can have multiple domains with same URL's. You can create a new domain and map all the routes to that domain. The domain is a String that will be treated like a regular expression.
Set the domain name with the domain method:
//Single domain:
Router :: get('customer/details', 'customer.details') -> domain('sub1\.example\.com');
//As an Array:
Router :: get('customer/details', 'customer.details') -> domain(['sub1\.example\.com', 'sub2\.example\.com']);
you can also group routes for domains:
Router :: domain(['sub1\.example\.com', 'sub2\.example\.com']) -> group(function($route) {
$route -> get('', 'home.index') -> controller('Home') -> action('index');
$route -> get('customer', 'customer.index') -> controller('Customer') -> action('index');
});
These routes will listen to:
If your application is listening to multiple domains and/or modules, don't forget to set a default 404 error route:
//Create default 404 error route
Router :: error(404', 'error.404a', true) -> module('FallbackApp') -> controller('Error') -> action('404');
//Create a 404 error route for the "App" module and "example.com" domain
Router :: module('App') -> controller('Error') -> domain('example\.com') -> group(function($route) {
$route -> error(404, 'error.404b') -> action('404');
});