slimphp / Slim

Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs.
http://slimframework.com
MIT License
11.98k stars 1.95k forks source link

How to handle PHP Fatal error #2927

Closed esetnik closed 4 years ago

esetnik commented 4 years ago

Let's say we have some code inside a controller that triggers PHP Fatal error: Uncaught TypeError: Argument 1 passed to.... How do we implement error handling for this scenario. Specifically, if this occurs I'd it to trigger my custom errorHandlerMiddleware.

class ExceptionHandler
{
    public static function registerMiddleware(\Slim\App $app):\Slim\Middleware\ErrorMiddleware
    {
        $errorHandler = function (
            Request $request,
            Throwable $exception,
            bool $displayErrorDetails,
            bool $logErrors,
            bool $logErrorDetails
        ) use ($app) {
            $container = $app->getContainer();
            $logger = $container->get('logger');
            $meta = null;
            try {
                throw $exception;
            } catch (BadRequestException $ex) {
                $statusCode = 400;
                $error = $ex->getMessage();
                $meta = $ex->getMeta();
                $logger->info('A bad request occurred', ['error' => $ex, 'meta' => $meta]);
            } catch (NotFoundException $ex) {
                $statusCode = 404;
                $error = $ex->getMessage() ? $ex->getMessage() : 'not found';
                $logger->info('Resource was not found', ['error' => $ex]);
            } catch (AuthorizationException $ex) {
                $statusCode = 403;
                $error = $ex->getMessage();
                $logger->info('An authorization exception occurred', ['error' => $ex]);
            } catch (AuthenticationException $ex) {
                $statusCode = 401;
                $error = $ex->getMessage();
                $logger->info('An authentication exception occurred', ['error' => $ex]);
            } catch (Exception $ex) {
                $statusCode = 500;
                $error = 'Something went wrong. Contact xxxxxx for help.';
                $logger->error('An error occurred', ['error' => $ex]);
                Sentry\captureException($ex);
            }

            $response = $app->getResponseFactory()->createResponse();

            return $response
              ->withJson(['message' => $error, 'meta' => $meta], $statusCode);
        };

        $errorMiddleware = $app->addErrorMiddleware(true, true, true);
        $errorMiddleware->setDefaultErrorHandler($errorHandler);
        return $errorMiddleware;
    }
}

I didn't find anything about this in the v4 documentation. I'm happy to submit a PR with updated docs once I understand what the correct approach is.

kwhat commented 4 years ago

I don't think you can "handle" it. A fatal error is just that, fatal.

l0gicgate commented 4 years ago

You can handle some of those exceptions via register_shutdown_function().

See https://github.com/slimphp/Slim-Skeleton/blob/f544b305f06a6a2743a033aad9fd20a3f4e3b250/public/index.php#L60 for an example

dlundgren commented 4 years ago

You could use catch(Exception | Throwable $ex)

l0gicgate commented 4 years ago

I'm closing this as resolved as no further input has been provided.