note 107509 added to language.oop5.magic

From: Date: Tue, 14 Feb 2012 10:54:18 +0000
Subject: note 107509 added to language.oop5.magic
Groups: php.notes 
Request: Send a blank email to php-notes+get-186121@lists.php.net to get a copy of this message
Ever wondered why you can't throw exceptions from __toString()? Yeah me too. Well now you can! This trick allows you to throw any type of exception from within a __toString(), with a full & correct backtrace. How does it work? Well PHP __toString() handling is not as strict in every case: throwing an Exception from __toString() triggers a fatal E_ERROR, but returning a non-string value from a __toString() triggers a non-fatal E_RECOVERABLE_ERROR. Add a little bookkeeping, and can circumvented this PHP deficiency! (tested to work PHP 5.3+) <?php set_error_handler(array('My_ToStringFixer', 'errorHandler')); error_reporting(E_ALL | E_STRICT); class My_ToStringFixer { protected static $_toStringException; public static function errorHandler($errorNumber, $errorMessage, $errorFile, $errorLine) { if (isset(self::$_toStringException)) { $exception = self::$_toStringException; // Always unset '_toStringException', we don't want a straggler to be found later if something came between the setting and the error self::$_toStringException = null; if (preg_match('~^Method .*::__toString\(\) must return a string value$~', $errorMessage)) throw $exception; } return false; } public static function throwToStringException($exception) { // Should not occur with prescribed usage, but in case of recursion: clean out exception, return a valid string, and weep if (isset(self::$_toStringException)) { self::$_toStringException = null; return ''; } self::$_toStringException = $exception; return null; } } class My_Class { public function doComplexStuff() { throw new Exception('Oh noes!'); } public function __toString() { try { // do your complex thing which might trigger an exception return $this->doComplexStuff(); } catch (Exception $e) { // The 'return' is required to trigger the trick return My_ToStringFixer::throwToStringException($e); } } } $x = new My_Class(); try { echo $x; } catch (Exception $e) { echo 'Caught Exception! : '. $e; } ?> ---- Server IP: 91.199.167.223 Probable Submitter: 2001:888:1dd1:0:223:dfff:fe91:d840 ---- Manual Page -- http://www.php.net/manual/en/language.oop5.magic.php Edit -- https://master.php.net/note/edit/107509 Del: integrated -- https://master.php.net/note/delete/107509/integrated Del: useless -- https://master.php.net/note/delete/107509/useless Del: bad code -- https://master.php.net/note/delete/107509/bad+code Del: spam -- https://master.php.net/note/delete/107509/spam Del: non-english -- https://master.php.net/note/delete/107509/non-english Del: in docs -- https://master.php.net/note/delete/107509/in+docs Del: other reasons-- https://master.php.net/note/delete/107509 Reject -- https://master.php.net/note/reject/107509 Search -- https://master.php.net/manage/user-notes.php

« previous php.notes (#186121) next »