Reputation: 2683
I have a very simple function to check whether an Entity exists in a bundle:
public function checkExists($bundle, $val)
{
try{
$this->em->getRepository($bundle.':'.$val);
}catch (MappingException $e){
return false;
}
return true;
}
So I have the following cases:
Input | Expected | Actual
'AppBundle', 'Company' | true | true
'AppBundle', 'NONEXISTANT' | false | false (MappingException caught)
'NONEXISTANT', 'Company' | false | 500 (ORMException not caught)
'NONEXISTANT', 'NONEXISTANT' | false | 500 (ORMException not caught)
So I see that the problem is that there are different exceptions thrown, but how could I return false for either of the cases of one part non-existant? Is there a "general" way to catch exceptions in symfony as catch (Exception $e)
with use Symfony\Component\Config\Definition\Exception\Exception;
does not catch it.
Upvotes: 3
Views: 2933
Reputation: 2014
Create Exception Listener and handle them there.
class ExceptionListener
{
/** @var LoggerInterface */
private $logger;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
public function onKernelException(GetResponseForExceptionEvent $event)
{
$e = $event->getException();
if ($e instanceof ValidationException) {
$this->logger->notice('Validation error' , $e->getViolations());
} elseif ($e instanceof DomainException) {
$this->logger->warning('Exception ' . get_class($e) , ['message' => $e->getMessage()]);
$event->setResponse(
new JsonResponse(['error' => $this->translator->trans($e->getOutMessage())], 400)
);
} else {
$event->setResponse(
new JsonResponse(['error' => $this->translator->trans('http.internal_server_error')], 500)
);
}
}
}
Update services.yml
app.exception_listener:
class: Application\Listeners\ExceptionListener
arguments: ['@domain.logger']
tags:
- { name: kernel.event_listener, event: kernel.exception }
Further reading about listeners and events https://symfony.com/doc/current/event_dispatcher.html
I am not sure that you should create situations that throw Mapping exceptions, when your application is shipped.
Upvotes: 1
Reputation: 40653
There's a couple of things to do: You can catch all exceptions firstly, then you can handle each one differently:
public function checkExists($bundle, $val)
{
try{
$this->em->getRepository($bundle.':'.$val);
} catch (\Exception $e){ // \Exception is the global scope exception
if ($e instanceof MappingException || $e instanceof ORMException) {
return false;
}
throw $e; //Rethrow it if you can't handle it here.
}
return true;
}
Alternatevely have multiple catches:
public function checkExists($bundle, $val)
{
try{
$this->em->getRepository($bundle.':'.$val);
} catch (MappingException $e){
return false;
} catch (ORMException $e) {
return false;
} //Other exceptions are still unhandled.
return true;
}
If you're using PHP 7.1 + then you can also do:
public function checkExists($bundle, $val)
{
try{
$this->em->getRepository($bundle.':'.$val);
} catch (MappingException | ORMException $e){ //Catch either MappingException or ORMException
return false;
} //Other exceptions are still unhandled.
return true;
}
Upvotes: 4