Skip to content

Instantly share code, notes, and snippets.

@mkoert
Last active April 8, 2020 21:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mkoert/642e804035f1860dc09bd92ff327fa77 to your computer and use it in GitHub Desktop.
Save mkoert/642e804035f1860dc09bd92ff327fa77 to your computer and use it in GitHub Desktop.
<?php declare(strict_types=1);
namespace ApiMhv\Http\EventListener;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
// use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class ExceptionListener
{
public function onKernelException(ExceptionEvent $event)
{
// You get the exception object from the received event
$exception = $event->getThrowable();
$message = sprintf(
'%s with code: %s',
$exception->getMessage(),
$exception->getCode()
);
// Customize your response object to display the exception details
// if($contentType)
$response = new JsonResponse();
$response->setContent($message);
// HttpExceptionInterface is a special type of exception that
// holds status code and header details
if ($exception instanceof HttpExceptionInterface) {
$response->setStatusCode($exception->getStatusCode());
$response->headers->replace($exception->getHeaders());
} elseif ($exception instanceof NotFoundHttpException) {
$response->setContent('{"errors": "not_found": "'.$message.'"}');
} else {
$response->setStatusCode(Response::HTTP_INTERNAL_SERVER_ERROR);
}
// sends the modified response object to the event
$event->setResponse($response);
}
}
----
<?php declare(strict_types=1);
namespace ApiMhv\Http\EventListener;
use Symfony\Component\HttpFoundation\Response;
class ExceptionResponseStrategyMap extends CoreFoundExceptionResponseStrategy
{
protected $map = [];
public function addResponse($key, ExceptionStrategyResponse $response): self
{
$map[$key] = $response;
return self;
}
public function getResponse($key, Response $response, \Exception $exception)
{
return $map[$key]->handle($response, $exception);
}
}
----
<?php declare(strict_types=1);
namespace ApiMhv\Http\EventListener;
use Symfony\Component\HttpFoundation\Response;
class NotFoundExceptionResponseStrategy extends CoreFoundExceptionResponseStrategy
{
public function handle(Response $response, \Exception $exception)
{
$response->setHeaders($response, $exception);
$response->setStatusCode($response, $exception);
$response->setContent('{"errors": "not_found": "'.$message.'"}');
return $response;
}
}
----
<?php declare(strict_types=1);
namespace ApiMhv\Http\EventListener;
use Symfony\Component\HttpFoundation\Response;
abstract class CoreFoundExceptionStrategyResponse
{
protected function setStatusCode(Response $response, $exception): Response
{
$response->setStatusCode($exception->getStatusCode());
return $response;
}
protected function setHeaders(Response $response, $exception): Resonse
{
$response->headers->replace($exception->getHeaders());
return $response;
}
}
----
<?php declare(strict_types=1);
namespace ApiMhv\Http\EventListener;
use Symfony\Component\HttpFoundation\JsonResponse;
interface ExceptionStrategyResponse
{
public function handle(JsonResponse $response, $exception);
}
@yvoyer
Copy link

yvoyer commented Apr 8, 2020

final class ExceptionListener
{
    /**
     * @var YourStrategy
     */
    private $strategy;
    public function __construct(YourStrategy $strategy)
    {
        $this->strategy = $strategy;
     }

    public function onKernelException(ExceptionEvent $event): Response
    {
        $event->setResponse($this->strategy->createResponse($event->getThrowable());
        // $event->stopPropagation();
    }
}

@yvoyer
Copy link

yvoyer commented Apr 8, 2020

$strategy = new ArrayStrategy(
	new NullStrategy(),
	new NotFoundStrategy(),
	new ServerErrorStrategy()
);

$listener = new ExceptionListner($strategy);


$listener->onKernelEvent(new Exception('whatever'));

$response // would be done 

@yvoyer
Copy link

yvoyer commented Apr 8, 2020

interface ResponseFailure 
{
    public function createResponse(Response $response, \Throwable $exception): Response;
    public function supportsExecption(\Throwable $execption): bool;
}

@yvoyer
Copy link

yvoyer commented Apr 8, 2020

final class ClosureStrategy implements YourStrrategy
{
    private $closure;

    public function __construct(\Closure $closure) {}
    public function modifyResponse(Response $response, \Throwable $exception): Response
    {
        $closure = $this->closure;
        return $closure($response, $exception);
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment