Can't catch symfony FatalErrorException
Solution 1
Ok. I've found a workaround. I use the property accessor component which throws simple exceptions, not fatal errors.
$pa = \Symfony\Component\PropertyAccess\PropertyAccess::createPropertyAccessor();
try {
$var = $pa->getValue($object, 'collection[0].item.name');
} catch(\Exception $e) {
$var = null;
}
Solution 2
Use Throwable class instead Exception class:
try {
$var = $object->getCollection()->first()->getItem()->getName();
} catch(\Throwable $e) {
$var = null;
$msg = $e->getMessage();
}
Since PHP 7.0 exceptions thrown from fatal and recoverable errors are instances of a new and separate exception class: Error
. This new Error
class implements Throwable
interface, which specifies methods nearly identical to those of Exception
. Because Throwable
is higher in hierarchy you can catch with it both, \Error and \Exception.
interface Throwable
|- Exception implements Throwable
|- ...
|- Error implements Throwable
|- TypeError extends Error
|- ParseError extends Error
|- ArithmeticError extends Error
|- DivisionByZeroError extends ArithmeticError
|- AssertionError extends Error
Solution 3
As you can see here, FatalErrorException extends ErrorException (PHP) that extends itself php Exception class.
Now that you have all this elements, you're ready for next step: as the name of exception says, this is a FatalError (a concept related to PHP and not with Symfony2; in that case they built a wrapper class for this error, maybe for interface purposes).
A PHP fatal error isn't a catchable one so is pretty useless to keep the code that could cause the FatalError, inside a try ... catch
block
You should check, as a common and good rule, whenever is possible for returned values before try to access them.
Update
Since I've seen an upvote to my answer after PHP7 was released, I would like to caveat that since PHP7 is possible to catch fatal errors so this answer is still valid but only for PHP versions < 7.
Jumi
Updated on August 22, 2022Comments
-
Jumi over 1 year
I have code like this:
try { $var = $object->getCollection()->first()->getItem()->getName(); } catch(\Exception $e) { $var = null; }
Of course i have communicative variable and method names. This is just demonstration.
So if my collection is empty the Collection::first() will return false. Then the getItem call will throw a Symfony\Component\Debug\Exception\FatalErrorException which won't be catched by the code above.
My question is that how can i catch this exception? I have long chains like this with many getters that can return null. So i prefer this way rather than checking every value for null.
-
Radu Murzea about 9 yearsUsing exceptions for logic/control flow is a bad idea. I hope you won't ship code blocks like the one above into any production environment.
-
Jumi about 9 yearsDo you know about a tool that has similar features to the default twig filter?
-
DonCallisto about 9 years@Jumi: what do you mean?
-
DonCallisto about 9 years@Jumi: I know about "default twig filter". What I can't understand here is what do you mean with "a tool"? What tool? A PHP one?
-
Jumi about 9 yearsYes. A library, a function, something that keeps me away from writing conditions for all getters. Like the symfony property accessor would return an object containing which call fails in the chain.
-
DonCallisto about 9 yearsI'm not aware of nothing like what you're asing. BTW as I told you, isn't a good practice to skip controls because, eventually, big issues could be found and your code will became shortly unstable
-
richard almost 9 years@RaduMurzea Actually its a very common pattern in some languages like Python, where they express it as "It is Easier to Ask for Forgiveness than Permission." (see en.wikipedia.org/wiki/Python_syntax_and_semantics#Exceptions)
-
Scott Buchanan over 5 yearsI can confirm this solves the issue, but I don't understand why. Symfony's
FatalErrorException
extends\ErrorException
, which extends\Exception
. The fact that PHP now hasError
as a base class doesn't seem relevant since it's not in the inheritance hierarchy forFatalErrorException
. Can anybody explain? -
NineToeNerd over 3 years@ScottBuchanan I figured out something interesting today. My issue was with Symfony's FatalThrowableError (which also extends ErrorException). I noticed that if you manually throw a FatalThrowableError in an Exception try/catch, it's caught. But I was seeing unhandled errors of this type in the application originating within an Exception try/catch. I'm using the Laravel framework, and I've deduced that the framework caught the unhandled TypeError (an Error, not an Exception) after my handler didn't catch it and wrapped it in a FatalThrowableError.