Slim 4 - How to handle errors by ourselves completely?

Created on 17 Jul 2019  路  8Comments  路  Source: slimphp/Slim

How can we handle errors by ourselves completely?

I get this error below:

Uncaught Slim\ExceptionHttpNotFoundException: Not found.

If I remove these lines:

// $callableResolver = $app->getCallableResolver();
// $responseFactory = $app->getResponseFactory();
// $errorMiddleware = new ErrorMiddleware($callableResolver, $responseFactory, true, true, true);
// $app->add($errorMiddleware);

Then, when we try to catch to the error through a middleware:

$app->add(function (Request $request, RequestHandler $handler) {

    try {
        $response = $handler->handle($request);
        $existingContent = (string) $response->getBody();
        ...
    } catch (\Exception $error) {
        $response = $handler->handle($error->getRequest());
        $data = [
            "status" => $error->getCode(),
            "messsage" => $error->getMessage()
        ];
        $payload = json_encode($data);
        $response->getBody()->write($payload);

        return $response
          ->withHeader('Content-Type', 'application/json')
          ->withStatus($status);
    };

});

We get the same error back:

Uncaught Slim\ExceptionHttpNotFoundException: Not found.

We are trying to make our custom error in the JSON format, for example:

{"status":404,"message":"page not found"}

Any ideas?

pending response

Most helpful comment

Another way to handle this is to define a default route after all your other route definitions:

    $app->any('{route:.*}', function(Request $request, Response $response) {
        $response = $response->withStatus(404, 'page not found');
        return $response;
    });

All 8 comments

By calling the handle() method of the handler in the catch-block again, the handler would throw the exception again. But this time, no one is there to catch this second exception.

In Slim 4 you could either define your custom error handler (and pass it to the ErrorMiddleware) or simply define custom error renderers (based on accepted content-types by your request or on a forced content-type).

More information can be found in the docs, currently in development: https://github.com/slimphp/Slim-Website/blob/gh-pages-4.x/docs/v4/middleware/error-handling.md

@adriansuter none of that actually works. giving up...

In my view, this should be made simpler. But it is way too complicated now.

@lautiamkok it does work, I think you're doing something wrong on your end. Where are you adding this middleware? It should be the very last middleware you add, right before that middleware should be the routing middleware, otherwise Slim automatically appends the RoutingMiddleware if it hasn't been appended manually, which means it would go in front of your error handling middleware, which means you wouldn't catch anything.

@l0gicgate let me check later again and get back to you later. there are some errors in the code in the doc by the way

slim should have left all the error handling alone from the year dot. how it handles errors just does not make sense. for example in slim 3.12, if i want to handle 404 and other errors myself, I have to write two blocks of code:

$container = new \Slim\Container();
$container['errorHandler'] = function ($container) {
    return function ($request, $response, $exception) use ($container) {
        // print_r(get_class_methods($exception));
        $message = $exception->getMessage();
        $code = $exception->getCode();

        $data = [
            "status" => $code,
            "message" => $message
        ];
        $payload = json_encode($data);
        $response->getBody()->write($payload);

        return $response
            ->withHeader('Content-Type', 'application/json')
            ->withStatus($code);
    };
};
$container['notFoundHandler'] = function ($container) {
    return function ($request, $response) use ($container) {
        return $response->withStatus(404)
            ->withHeader('Content-Type', 'text/html')
            ->write('Page not found');
    };
};

It should just be one block of code. also, errorHandler and notFoundHandler work differently. they should work the same way.

My personal view on these lines below for handling error in slim 4:

$callableResolver = $app->getCallableResolver();
$responseFactory = $app->getResponseFactory();
$errorMiddleware = new ErrorMiddleware($callableResolver, $responseFactory, true, true, true);
$app->add($errorMiddleware);

I am not sure if this is a PSR standard or not but it is too ugly to read and to understand what is going on.

I don't know what these two $callableResolver and $responseFactory are doing there. if they are not helping us to understand by reading them, they shouldn't be there.

this is just my opinion.

That is dependency injection. As the middleware needs to have the callable resolver and the response factory, they would be given to the middleware. That way, the middleware is as independent as possible from the rest.

I鈥檓 closing this as resolved. The docs are clear. If you dislike the architecture you can always use a different framework. You鈥檙e also more than welcome to contribute when those architecture decisions are being made, the PRs and discussions are public.

Another way to handle this is to define a default route after all your other route definitions:

    $app->any('{route:.*}', function(Request $request, Response $response) {
        $response = $response->withStatus(404, 'page not found');
        return $response;
    });
Was this page helpful?
0 / 5 - 0 ratings

Related issues

codeguy picture codeguy  路  43Comments

grikdotnet picture grikdotnet  路  54Comments

l0gicgate picture l0gicgate  路  83Comments

Bilge picture Bilge  路  28Comments

akrabat picture akrabat  路  43Comments