Symfony custom error exception response

Mukhiddin Jumaniyazov
2 min readSep 14, 2023

--

When we start writing API we need own Error Exception depended our logic and we want pretty error response to client when our logic exception throw error

Let’s imagine we need to check before checkout that are goods available in stock.

create own exception

<?php

class OutOfStockException extends \Exception {

private int $product;

private int $count;

private int $shortageCount;

public function __construct(int $product, int $count, int $shortageCount)
{
parent::__construct('Product is out of stock');
$this->product = $product;
$this->count = $count;
$this->shortageCount = $shortageCount;
}

public function getProduct(): int
{
return $this->product;
}

public function getCount(): int
{
return $this->count;
}

public function getShortageCount(): int
{
return $this->shortageCount;
}
}

The first method is catch error and response error data to client in controller action

class OrderController extends AbstractController
{

public function checkoutAction()
{
try {
// checkout logic will be here
} catch (OutOfStockException $e) {
return JsonResponse::create([
'product' => $e->getProduct(),
'count' => $e->getCount(),
'shortageCount' => $e->getShortageCount(),
'message' => $e->getMessage(),
]);
}
}
}

The next method which are very clearly and wisely by using Symfony event listener

we create Interface for grouping Exceptions

interface ListenableExceptionInterface
{

public function toArray(): array;
}

And our class should be implement this interface

create event listener class for catch our specific exception

<?php

class OutOfStockException extends \Exception implements ListenableExceptionInterface {

// above body getter and constructor code will be here

public function toArray(): array
{
return [
'product' => $this->getProduct(),
'count' => $this->getCount(),
'shortageCount' => $this->getShortageCount(),
'message' => $this->getMessage(),
];
}
}

And our listener catch all exceptions which was implemented by ListenableExceptionInterface

class AdvanceExceptionListener
{
public function onKernelException(ExceptionEvent $event)
{
$exception = $event->getException();
if (!$exception instanceof ListenableExceptionInterface) {
return;
}

$response = new JsonResponse($exception->toArray(), $exception->getCode());
$event->setResponse($response);
}
}

in our service we throw exception

<?php

class CheckoutManager {

public function checkout(Product $product, int $count) {
if($product->getCount() < $count){
throw new OutOfStockException($product->getId(), $count, $count - $product->getCount());
}
}
}

We don’t need catch exception in out controller action, our Listener automatic listen this exception and return response

--

--

Mukhiddin Jumaniyazov

Senior Full Stack Software engineer (Php/Symfony/NestJs/ReactJs