🧰 Provides Symfony Messenger middleware to capture any thrown exception and map it into Symfony Validator violations format in accordance with message property path.
-
Install via composer
composer require phphd/exceptional-validation-bundle
-
Enable the bundle in the
bundles.php
PhPhD\ExceptionalValidationBundle\PhdExceptionalValidationBundle::class => ['all' => true],
To leverage features of this bundle, you should add phd_exceptional_validation
middleware to the list:
framework:
messenger:
buses:
command.bus:
middleware:
- validation
+ - phd_exceptional_validation
- doctrine_transaction
When the exception is thrown from the handler, the message that is mapped by #[ExceptionalValidation]
attribute is
analyzed for #[Capture]
properties attributes. If a mapping defines this exception, it will be processed.
Here is an example of mapped message:
use PhPhD\ExceptionalValidation;
#[ExceptionalValidation]
final readonly class CreateVacationRequestCommand
{
public function __construct(
public Employee $employee,
#[ExceptionalValidation\Capture(VacationTypeNotFoundException::class, 'vacation.type_not_found')]
public int $vacationTypeId,
#[Assert\DateTime]
public string $startDate,
#[Assert\DateTime]
#[ExceptionalValidation\Capture(InsufficientVacationBalanceException::class, 'vacation.insufficient_balance')]
public string $endDate,
) {
}
}
In addition to standard symfony validator constraints, certain properties also have #[Capture]
attributes. These
attributes specify the particular exception class to be intercepted and the corresponding validation message to be shown
when this exception occurs.
Finally, when the exception has been captured, ExceptionalValidationFailedException
is thrown:
$message = new CreateVacationRequestCommand($user, $vacationTypeId, $startDate, $endDate);
try {
$this->commandBus->dispatch($message);
} catch (ExceptionalValidationFailedException $exception) {
// Is thrown when handler failed with VacationTypeNotFoundException or InsufficientVacationBalanceException
return $this->render('vacationForm.html.twig', ['errors' => $exception->getViolations()]);
}
As you can see in the example above, $exception
object has constraint violation list with respectively mapped error
messages. This errors list may be used in various ways such as displaying on an HTML page, formatting them into a JSON
response, logging into file, rethrowing different exception, or any other specific requirement you might have.