$app->notFound() for Slim v3
In Slim v2, there is the option to invoke the error or not found handler with
respectively $app->error()
or $app->notFound()
inside your
controller/closure. In Slim v3, the feature has been removed* but there is a
way to manage the same result with middleware.
To clarify from the start, Slim automatically calls the not found handler when a request does not match any of your routes. But there are other cases: you query a DB item and got zero results, for example. In these cases, you want to trigger the 404 page yourself.
The principle idea is to set a Response
with a 404 status code and without
any body. This way, you have the minimal required code to trigger a 404
reduced to this:
return $response->withStatus(404);
If you are in need of a 404 page with a non-standard body (i.e. where your page design of the not found page is not the default 404 design you implemented), you can write a response to this body too. The middleware will check if any body is set, and only without body the default error handler is triggered.
With Slim v3, PSR-7 and middleware, everything above can be accomplished in a few lines of code:
// $c is the DI container of Slim
$app->add(function ($request, $response, $next) use ($c) {
// First execute anything else
$response = $next($request, $response);
// Check if the response should render a 404
if (404 === $response->getStatusCode() &&
0 === $response->getBody()->getSize()
) {
// A 404 should be invoked
$handler = $c['notFoundHandler'];
return $handler($request, $response);
}
// Any other request, pass on current response
return $response;
}
In a similar fashion, the error handler could be invoked when you return a
500
error, and so on. With middleware, the layered design really shines and
although it is a very small example, this already shows the power of
middleware.
*) The feature was not actively “removed” but during the major rewrite of Slim the existing feature simply hasn’t been implemented back. And actually I think above is a cleaner solution than it existed before.