I want to create a Slim 4 compatible custom error page /JSON reply that is returned, when a non-existing route is request.
I've recently upgraded from Slim 3 to Slim 4. With Slim 3, I had a default route that perfectly did the job:
$app->any('/[{path:.*}]', function (Request $request, Response $response, array $args) {
// catching any other requests...
/* ... creating JSON error object and write it to $slimresponse ... */
return ($slimresponse);
});
However, when I do this in Slim 4, I get an error
Type: FastRoute\BadRouteException
Code: 0
Message: Cannot register two routes matching "/" for method "GET"
This obviouosly means that Slim recognizes this as double entry for GET /, which is disallowed in Slim 4.
This article also provided no help for Slim 4, unfortunately.
Furthermore, according to https://www.javaer101.com/en/article/13830039.html, I've tried to add
$app->notFound(function () use ($app) {
$app->response->setStatus(403);
echo "Forbidden";
//output 'access denied', redirect to login page or whatever you want to do.
});
to my routes.php, but it doesn't work:
Call to undefined method Slim\App::notFound()
Finally, I've also tried to create an error handling method (specifically for HttpNotFoundException, although I don't know how to separate HttpNotImplementedException) https://www.slimframework.com/docs/v4/middleware/error-handling.html, without any success.
Any help is highly appreciated.
I'd posted the question after searching for two or more hours.
After submitting the question, I've found the answer here. https://odan.github.io/2020/05/27/slim4-error-handling.html#catching-404-not-found-errors
Here is my new middleware.php:
use Slim\App;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Slim\Exception\HttpNotFoundException;
use Slim\Middleware\ErrorMiddleware;
use Middlewares\TrailingSlash;
use Slim\Psr7\Response;
return function (App $app) {
// Parse json, form data and xml
$app->addBodyParsingMiddleware();
// Add the Slim built-in routing middleware
$app->addRoutingMiddleware();
// always add a trailing slash
$app->add(new TrailingSlash(true));
// Add BasePathMiddleware
$app->add(BasePathMiddleware::class);
// HttpNotFoundException
$app->add(function (ServerRequestInterface $request,
RequestHandlerInterface $handler) {
try {
return $handler->handle($request);
} catch (HttpNotFoundException $httpException) {
$response = (new Response())->withStatus(404);
$response->getBody()->write('404 Not found');
return $response;
}
});
// Catch exceptions and errors
$app->add(ErrorMiddleware::class);
};
For everyone looking for an extension with another exception class, extend the code above by:
try {
return $handler->handle($request);
} catch (HttpNotFoundException $httpException) {
$response = (new Response())->withStatus(404);
$response->getBody()->write('404 Not found');
return $response;
} catch (HttpMethodNotAllowedException $httpException) {
$response = (new Response())->withStatus(405);
$response->getBody()->write('405 Method not allowed. Please use one of the following: '.implode(',',$httpException->getAllowedMethods()));
return $response;
}
Other exception classes can be found on https://github.com/slimphp/Slim/tree/4.x/Slim/Exception
This is how you can get and display the exception class for developing/debugging purposes:
} catch (Exception $e) {
$response = (new Response())->withStatus(500);
$response->getBody()->write(get_class($e));
return $response;
}