diff --git a/Slim/Middleware/ErrorMiddleware.php b/Slim/Middleware/ErrorMiddleware.php index 6febfa383..170e68734 100644 --- a/Slim/Middleware/ErrorMiddleware.php +++ b/Slim/Middleware/ErrorMiddleware.php @@ -188,7 +188,7 @@ public function setDefaultErrorHandler($handler): self * The callable signature MUST match the ErrorHandlerInterface * * Pass true to $handleSubclasses to make the handler handle all subclasses of - * the type as well. + * the type as well. Pass an array of classes to make the same function handle multiple exceptions. * * @see \Slim\Interfaces\ErrorHandlerInterface * @@ -201,19 +201,39 @@ public function setDefaultErrorHandler($handler): self * The callable MUST return an instance of * \Psr\Http\Message\ResponseInterface. * - * @param string $type Exception/Throwable name. ie: RuntimeException::class + * @param string|string[] $typeOrTypes Exception/Throwable name. + * ie: RuntimeException::class or an array of classes + * ie: [HttpNotFoundException::class, HttpMethodNotAllowedException::class] * @param callable|ErrorHandlerInterface $handler * @param bool $handleSubclasses * @return self */ - public function setErrorHandler(string $type, $handler, bool $handleSubclasses = false): self + public function setErrorHandler($typeOrTypes, $handler, bool $handleSubclasses = false): self + { + if (is_array($typeOrTypes)) { + foreach ($typeOrTypes as $type) { + $this->addErrorHandler($type, $handler, $handleSubclasses); + } + } else { + $this->addErrorHandler($typeOrTypes, $handler, $handleSubclasses); + } + + return $this; + } + + /** + * Used internally to avoid code repetition when passing multiple exceptions to setErrorHandler(). + * @param string $type + * @param callable|ErrorHandlerInterface $handler + * @param bool $handleSubclasses + * @return void + */ + private function addErrorHandler(string $type, $handler, bool $handleSubclasses): void { if ($handleSubclasses) { $this->subClassHandlers[$type] = $handler; } else { $this->handlers[$type] = $handler; } - - return $this; } } diff --git a/tests/Middleware/ErrorMiddlewareTest.php b/tests/Middleware/ErrorMiddlewareTest.php index 83ba29064..8326f0960 100644 --- a/tests/Middleware/ErrorMiddlewareTest.php +++ b/tests/Middleware/ErrorMiddlewareTest.php @@ -205,6 +205,45 @@ public function testSuperclassExceptionHandlerDoesNotHandleSubclassException() $this->expectOutputString('Oops..'); } + public function testHandleMultipleExceptionsAddedAsArray() + { + $responseFactory = $this->getResponseFactory(); + $app = new App($responseFactory); + $callableResolver = $app->getCallableResolver(); + + $mw = new ErrorMiddleware($callableResolver, $this->getResponseFactory(), false, false, false); + + $app->add(function ($request, $handler) { + throw new InvalidArgumentException('This is an invalid argument exception...'); + }); + + $handler = (function (ServerRequestInterface $request, $exception) { + $response = $this->createResponse(); + $response->getBody()->write($exception->getMessage()); + return $response; + }); + + $mw->setErrorHandler([LogicException::class, InvalidArgumentException::class], $handler->bindTo($this)); + + $mw->setDefaultErrorHandler((function () { + $response = $this->createResponse(); + $response->getBody()->write('Oops..'); + return $response; + })->bindTo($this)); + + $app->add($mw); + + $app->get('/foo', function (ServerRequestInterface $request, ResponseInterface $response) { + $response->getBody()->write('...'); + return $response; + }); + + $request = $this->createServerRequest('/foo'); + $app->run($request); + + $this->expectOutputString('This is an invalid argument exception...'); + } + public function testErrorHandlerHandlesThrowables() { $responseFactory = $this->getResponseFactory();