The astute reader has noticed that our framework hardcodes the way specific "code" (the templates) is run. For simple pages like the ones we have created so far, that's not a problem, but if you want to add more logic, you would be forced to put the logic into the template itself, which is probably not a good idea, especially if you still have the separation of concerns principle in mind.
Let's separate the template code from the logic by adding a new layer: the controller: The controller mission is to generate a Response based on the information conveyed by the client Request.
Change the template rendering part of the framework to read as follows:
<?php
// example.com/web/front.php
// ...
try {
$request->attributes->add($matcher->match($request->getPathInfo()));
$response = call_user_func('render_template', $request);
} catch (Routing\Exception\ResourceNotFoundException $e) {
$response = new Response('Not Found', 404);
} catch (Exception $e) {
$response = new Response('An error occurred', 500);
}
As the rendering is now done by an external function (render_template()
here), we need to pass to it the attributes extracted from the URL. We could
have passed them as an additional argument to render_template(), but
instead, let's use another feature of the Request class called
attributes: Request attributes lets you attach additional information about
the Request that is not directly related to the HTTP Request data.
You can now create the render_template() function, a generic controller
that renders a template when there is no specific logic. To keep the same
template as before, request attributes are extracted before the template is
rendered:
function render_template($request)
{
extract($request->attributes->all(), EXTR_SKIP);
ob_start();
include sprintf(__DIR__.'/../src/pages/%s.php', $_route);
return new Response(ob_get_clean());
}
As render_template is used as an argument to the PHP call_user_func()
function, we can replace it with any valid PHP callbacks. This allows us to
use a function, an anonymous function, or a method of a class as a
controller... your choice.
As a convention, for each route, the associated controller is configured via
the _controller route attribute:
$routes->add('heTruncated by Planet PHP, read more at the original (another 13773 bytes)