Nice uses FastRoute as a router, but also provides URL generation using named routes.
Using the map
method on RouteCollector
, you may choose to pass in a name as the second parameter. You can also
pass in null
to leave the route un-named, as we saw in the original example.
Below is a slightly different example of the introduction application.
use Symfony\Component\HttpFoundation\Response;
use Nice\Application;
use Nice\Router\RouteCollector;
$app = new Application();
// Configure your routes
$app->set('routes', function (RouteCollector $r) {
$r->map('/', 'home', function (Application $app) {
$url = $app->get('router.url_generator')->generate('hello', array('name' => 'Tyler'));
return new Response('Hello, world. <a href="' . $url . '">Hello, Tyler.</a>');
});
$r->map('/hello/{name}', 'hello', function (Application $app, $name) {
return new Response('Hello, ' . $name . '!');
});
});
We used map
and passed the name of the route as the second parameter. Inside the first action is an
example of using the URL generator to generate a route for the route named hello
.
You can also generate absolute URLs by passing true
as the third parameter.
The full generate
method signature is:
interface UrlGeneratorInterface
{
/**
* Generate a URL for the given route
*
* @param string $name The name of the route to generate a url for
* @param array $parameters Parameters to pass to the route
* @param bool $absolute If true, the generated route should be absolute
*
* @return string
*/
public function generate($name, array $parameters = array(), $absolute = false);
}
The fourth parameter in map
defines which HTTP methods the action should respond to. It takes either a string or
an array of strings. By default, routes will listen to GET method requests only.
For example, an action that should respond only to POST would pass: ['POST']
or array('POST')
as the value:
$app->set('routes', function (RouteCollector $r) {
$r->map('/user/{id}/edit', 'user_edit', function (Application $app, $id) {
// ... do something useful
}, ['POST']);
});
Tip: You may notice that you are able to map one action to multiple HTTP methods by passing an array like
['GET', 'POST']
. In general, this should be avoided as code should do one thing and one thing only; GET for fetching and POST for updating may share some code, but combining the two into a single action may be considered bad practice.See the Wikipedia article on the single responsibility principle for a more thorough explanation.
You may want to segregate actions into controller classes rather than having a mess of Closures in your front controller. By default, Nice allows the alternate syntax defining a class and action method:
$app->set('routes', function (RouteCollector $r) {
$r->map('/user/{id}/edit', 'user_edit', 'UserController::editAction');
$r->map('/user/{id}/update', 'user_update', 'UserController::updateAction');
});
Note: The specified controller class is actually instantiated, and then the action method is called on that object. If you want to use static action methods, you must use the array callable syntax:
['UserController', 'staticAction']
orarray('UserController', 'staticAction')
.
As an additional step, you may want access to the service container inside your controllers. Implement the
Symfony\Component\DependencyInjection\ContainerAwareInterface
and when your controller is resolved and
instantiated, the service container will be injected using the controller's setContainer
method.
Tip: Injecting the service container itself is considered an anti-pattern, turning the container into a service locator rather than proper dependency injection. Consider using controllers as services instead.
Notice: Nice 1.1 introduced support for controllers as services. Make sure you've got the latest version to make use of this feature.
Providing your controller actions with the service container itself is a quick, easy way to get up and running. For most apps, however, registering controllers as services is the preferred solution.
Register your route handler with a single colon, separating the name of the service and the name of the
action method. For example, acme.some_controller:indexAction
will use the acme.some_controller
service,
calling its indexAction
method.
Reworking the previous example, we need to add a custom dependency injection extension.
class AcmeExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container)
{
// Register our controller as a service, also configuring any dependencies.
$container->register('acme.user_controller', 'UserController')
->addArgument(new Reference('doctrine.orm.entity_manager'));
}
}
Back in your front controller, web/index.php
:
// ...
$app->appendExtension(new AcmeExtension());
$app->set('routes', function (RouteCollector $r) {
$r->map('/user/{id}/edit', 'user_edit', 'acme.user_controller:editAction');
$r->map('/user/{id}/update', 'user_update', 'acme.user_controller:updateAction');
});
Optimizing your app is important. Nice relies heavily on caching to stay performant. See here for details on customizing caching in your application.
Powered by Codex 1.1.0