Assuming I have a parent class:
class Parent {
//...
}
and a child class with methods:
class Child extends Parent {
public function foo() {
// process and return data
}
public function bar() {
// process and return data
}
// way more methods...
}
then is there a generic way in PHP to handle any exceptions thrown in the child methods? For example, a handler in the Parent class? Or do I need to wrap all the methods bodies in a separate try-catch block?
What I want to achieve, is to return an empty array()
if any of the child methods throw any kind of exception.
Yes, this is possible. Well, a parent cannot know all possible child methods, but it can know when an undefined method is called by implementing the __call
magic method.
We can use this method to create a try-catch "wrapper" dynamically.
Add this method to your parent:
public function __call($method, $args)
{
// If method call ends with 'Safe'
$isSafeMethod = substr($method, -strlen('Safe')) === 'Safe';
if (!$isSafeMethod) {
trigger_error('Call to undefined method '.__CLASS__.'::'.$method.'()', E_USER_ERROR);
return null;
}
// Strip 'Safe' suffix from method name
$wrappedMethodName = substr($method, 0, strpos($method, 'Safe'));
try {
return $this->$wrappedMethodName($args);
} catch (Exception $e) {
return [];
}
}
Now, anytime you want to invoke this try-catch wrapper, just append "Safe" to the method name that you want to wrap. Full code + example:
class TestParent {
public function __call($method, $args)
{
// If method call ends with 'Safe'
$isSafeMethod = substr($method, -strlen('Safe')) === 'Safe';
if (!$isSafeMethod) {
trigger_error('Call to undefined method '.__CLASS__.'::'.$method.'()', E_USER_ERROR);
return null;
}
// Strip 'Safe' suffix from method name
$wrappedMethodName = substr($method, 0, strpos($method, 'Safe'));
try {
return $this->$wrappedMethodName($args);
} catch (Exception $e) {
return [];
}
}
}
class TestChild extends TestParent {
public function throwingMethod()
{
throw new RuntimeException();
}
public function succeedingMethod()
{
return 'Success';
}
}
$child = new TestChild();
// With 'Safe' try-catch invoked in parent
var_dump($child->throwingMethodSafe()); // Empty array
var_dump($child->succeedingMethodSafe()); // 'Success'
// Without 'Safe' try-catch
var_dump($child->throwingMethod()); // throws RuntimeException as expected
Output in 3v4l.org
Sidenote: Please don't catch the Exception
class as it is too general and will make debugging a living hell later on ("Why is this method returning an array??")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With