Edit report at https://bugs.php.net/bug.php?id=53648&edit=1

 ID:                 53648
 Comment by:         benjamin dot morel at strictcoding dot co dot uk
 Reported by:        clicky at erebot dot net
 Summary:            Allow __toString() to throw exceptions
 Status:             Open
 Type:               Feature/Change Request
 Package:            Class/Object related
 PHP Version:        5.3.4
 Block user comment: N
 Private report:     N

 New Comment:

@nikic: too bad, I did not imagine that this was a problem with PHP internals, 
but 
rather an architectural choice. Can we keep this feature request open, until 
someone finds a solution? It would be good to keep this as a target!


Previous Comments:
------------------------------------------------------------------------
[2012-12-04 16:41:50] ni...@php.net

@benjamin: I don't think anyone opposes this feature request, it's just too 
hard to implement. Allowing __toString to throw exceptions would require any 
internal code doing a zval to string conversion to be exception-safe. See also: 
http://markmail.org/message/lkpmpnhrvcbafhkd

------------------------------------------------------------------------
[2012-12-04 12:57:36] benjamin dot morel at strictcoding dot co dot uk

I strongly support this feature request.
I haven't read any valid supportive argument so far, for keeping this behaviour 
as 
it is currently.
In case someone would be worried about backward compatibility issues, this 
change 
could be introduced with the next major version, PHP 5.5!

I would be grateful if a member of the PHP team could review this request.

------------------------------------------------------------------------
[2011-11-10 04:05:48] dqhendricks at hotmail dot com

this problem is causing me such a headache. i'm not even trying to convert an 
object 
to a string and i'm getting this error. the bug become such a pain to track. i 
have 
an active record that lazy loads child objects through __get. so even though im 
just 
trying to print a property of an object that is a string, the fact that a __get 
is 
used to get that object, prevents me from throwing exceptions. it looks like 
this 
echo $activerecord->childobject->somestring;

------------------------------------------------------------------------
[2011-01-04 14:45:29] clicky at erebot dot net

Description:
------------
Currently, when casting an object with __toString() to a string, __toString() 
is not allowed to throw an exception.
Trying to do so triggers an E_ERROR "Method %s::__toString() must not throw an 
exception".
IMHO, this is counter-intuitive, especially since calling that object's 
__toString() method directly would correctly throw the exception.

I propose to allow __toString() to throw exceptions.

Note: this was already reported in http://bugs.php.net/bug.php?id=50699 but 
marked as bogus with the only explanation being "__toString must not throw".
So, I'm marking this as a feature request rather than a bug, since the current 
behaviour seems to be expected (though it is not documented in 
http://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.tostring).

I also found this entry 
http://stackoverflow.com/questions/2429642/why-its-impossible-to-throw-exception-from-tostring
 which cites Johannes saying this requires major changes in the code. However, 
the article mentioned is from 2007 and I think the limitations in ZE that 
prevented this to be implemented were lifted since then.

I'm not very versed in PHP's inner workings, but attached is a tentative patch 
which seems to fix this issue.

Test script:
---------------
<?php

class CustomException
extends Exception
{
}

class Foo
{
    public function __toString()
    {
        throw new CustomException('oops!');
    }
}


$foo = new Foo();
try {
    var_dump((string) $foo);
}
catch (CustomException $e) {
    var_dump($e);
}

?>

Expected result:
----------------
object(CustomException)#2 (7) {
  ["message":protected]=>
  string(5) "oops!"
  ["string":"Exception":private]=>
  string(0) ""
  ["code":protected]=>
  int(0)
  ["file":protected]=>
  string(17) "/tmp/toString.php"
  ["line":protected]=>
  int(65)
  ["trace":"Exception":private]=>
  array(1) {
    [0]=>
    array(6) {
      ["file"]=>
      string(17) "/tmp/toString.php"
      ["line"]=>
      int(71)
      ["function"]=>
      string(10) "__toString"
      ["class"]=>
      string(3) "Foo"
      ["type"]=>
      string(2) "->"
      ["args"]=>
      array(0) {
      }
    }
  }
  ["previous":"Exception":private]=>
  NULL
}


Actual result:
--------------
PHP Fatal error:  Method Foo::__toString() must not throw an exception in 
/tmp/toString.php on line 0
PHP Stack trace:
PHP   1. {main}() /tmp/toString.php:0


------------------------------------------------------------------------



-- 
Edit this bug report at https://bugs.php.net/bug.php?id=53648&edit=1

Reply via email to