Yes it is possible. Well, the parent cannot know all the possible child methods, but he can know when the undefined method is called, implementing the __call magic method.
We can use this method to dynamically create a try-catch wrapper.
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 call this try-catch wrapper, just add "Safe" to the name of the method 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 to 3v4l.org
Sidenote: Please do not catch the Exception class, because it is too general and will debug the living hell later ("Why does this method return an array?")
source share