Exception::__toString() not called

php.internals

Timm Friebe

22 years ago
Hi, Both of the following examples used to output the Exception::__toString() output, which they don't anymore: $ php-dev -r '$e= new Exception(); echo $e, "\n";' Object id #1 $ php-dev -r '$e= new Exception(); echo (string)$e, "\n";' Object id #1 Works fine for userland objects: $ php-dev -r 'class Foo { function __toString() { return "foo"; }} echo new Foo(), "\n";' foo - Timm

Marcus Börger

22 years ago
Hello Timm, hello Andi, i htought i had a better solution to the __toString() problem. But then i found out why we made it so complex. The reason IIRC was to prevent __toString() being called everywhere automatically when it is a user function. Havin said this the solution is very easy. We expand the signature of cast_object to inform about exactly this - whether user space functions may be called or not. From _convert_to_string() we set that param to zero and from make_printable_zval we set it to 1 and inside the cast function we only need to verify the type of the function if necessary. Even better would be to add a flag that disallows usercode functions. Because with such a flag we do not have a problem if a conversion calls an internal method which then calls a userspace function which it shouldn't. Anid? Tuesday, March 16, 2004, 10:22:24 PM, you wrote:
> Hi,
> Both of the following examples used to output the > Exception::__toString() output, which they don't anymore:
> $ php-dev -r '$e= new Exception(); echo $e, "\n";' > Object id #1
> $ php-dev -r '$e= new Exception(); echo (string)$e, "\n";' > Object id #1
> Works fine for userland objects:
> $ php-dev -r 'class Foo { function __toString() { return "foo"; }} echo > new Foo(), "\n";' > foo
> - Timm
-- Best regards, Marcus mailto:helly@php.net

Marcus Börger

22 years ago
> Hello Timm, hello Andi,
well i forgot to mentione a problem description: Some internal classes copy the standard handler table. And hence their cast handler is set to NULL. This we need to avoid. But still standard objects may not be converted to strings everywhere.
> i htought i had a better solution to the __toString() problem. > But then i found out why we made it so complex. The reason IIRC > was to prevent __toString() being called everywhere automatically > when it is a user function.
> Havin said this the solution is very easy. We expand the signature > of cast_object to inform about exactly this - whether user space > functions may be called or not. From _convert_to_string() we set > that param to zero and from make_printable_zval we set it to 1 > and inside the cast function we only need to verify the type of > the function if necessary.
> Even better would be to add a flag that disallows usercode functions. > Because with such a flag we do not have a problem if a conversion > calls an internal method which then calls a userspace function which > it shouldn't.
> Anid?
> Tuesday, March 16, 2004, 10:22:24 PM, you wrote:
>> Hi,
>> Both of the following examples used to output the >> Exception::__toString() output, which they don't anymore:
>> $ php-dev -r '$e= new Exception(); echo $e, "\n";' >> Object id #1
>> $ php-dev -r '$e= new Exception(); echo (string)$e, "\n";' >> Object id #1
>> Works fine for userland objects:
>> $ php-dev -r 'class Foo { function __toString() { return "foo"; }} echo >> new Foo(), "\n";' >> foo
-- Best regards, Marcus mailto:helly@php.net

Andi Gutmans

22 years ago
The Exception class should support cast_object(). I don't see why we need to add extra flags. Andi At 11:45 PM 3/16/2004 +0100, Marcus Boerger wrote:

Marcus Börger

22 years ago
Hello Andi, the problem is that we have many classes that the handler table to behave mostly like a default php object. We'd need to manually set the cast handler for all of them. marcus Wednesday, March 17, 2004, 9:45:26 AM, you wrote:

Andi Gutmans

22 years ago
At 09:49 AM 3/17/2004 +0100, Marcus Boerger wrote:
>Hello Andi, > >the problem is that we have many classes that the handler table to behave >mostly like a default php object. We'd need to manually set the cast handler >for all of them.
Yes, that is correct. Don't forget that cast_object() can not call user-defined __toString(). If you have a better way then let me know but I don't want to do some hack just because other objects are copying the stdclass'es handlers (which they shouldn't really do in the first place or at least, I don't have a contract with internal classes about it). Andi

Andi Gutmans

22 years ago
Marcus and rest, Zeev and I took a long look at the whole __toString() issue. There is a problem today that make_printabl_zval() is being called in many places, some of which can't cope with a user-land __toString() being called. In order to support this we will have to do a complete restructuring of the opcodes something we don't want to do pre-5.0.0. Due to this reason we currently have a safe automatic __toString() call in print/echo. This will work with any overloaded extension which implements get_method(). We will try and call __toString() and if we don't succeed we will call the standard zval printing function. All other places, such as concat and friends will not automatically call __toString(). Internal extensions such as SimpleXML which implement cast_object() are NOT affected by this change. We continue to honor their conversion requests as usual. I will commit the patches soon and will roll RC1RC2. Hopefully tomorrow I'll roll the final RC1. Andi At 09:49 AM 3/17/2004 +0100, Marcus Boerger wrote:

Hans Lellelid

22 years ago
Hi Andi, Quick question - Andi Gutmans wrote:
> Marcus and rest, > > Zeev and I took a long look at the whole __toString() issue. There is a > problem today that make_printabl_zval() is being called in many places, > some of which can't cope with a user-land __toString() being called. In > order to support this we will have to do a complete restructuring of the > opcodes something we don't want to do pre-5.0.0.
Just to clarify, this is only for internal classes like Exception, right? Userland __toString() will continue to be invoked when an explicit (string) cast (or concat, etc.) is used, correct? Thanks, Hans

Andi Gutmans

22 years ago
At 11:05 AM 3/17/2004 -0500, Hans Lellelid wrote:
>Hi Andi, > >Quick question - > >Andi Gutmans wrote: >>Marcus and rest, >>Zeev and I took a long look at the whole __toString() issue. There is a >>problem today that make_printabl_zval() is being called in many places, >>some of which can't cope with a user-land __toString() being called. In >>order to support this we will have to do a complete restructuring of the >>opcodes something we don't want to do pre-5.0.0. > >Just to clarify, this is only for internal classes like Exception, >right? Userland __toString() will continue to be invoked when an explicit >(string) cast (or concat, etc.) is used, correct?
Wrong. The only time userland __toString() will be invoked will be in print/eval. We found that all the places where this happened automaticall were buggy due to the way our opcode mechanism works. It's not a quick fix to support this and is not something I would like to do before 5.0.0. You're going to have to explicitly call __toString() in anything except for print/eval. Internal classes which support the cast_object() callback (such as SimpleXML) will always be called. Sorry but it's the right way to go for now. Once we release 5.0.0 we should discuss exactly in which additional cases it should be called. Andi

Hans Lellelid

22 years ago
Hi - Andi Gutmans wrote:
>> Just to clarify, this is only for internal classes like Exception, >> right? Userland __toString() will continue to be invoked when an >> explicit (string) cast (or concat, etc.) is used, correct? > > > Wrong. The only time userland __toString() will be invoked will be in > print/eval. We found that all the places where this happened > automaticall were buggy due to the way our opcode mechanism works. It's > not a quick fix to support this and is not something I would like to do > before 5.0.0. You're going to have to explicitly call __toString() in > anything except for print/eval.
Ugh ... that really sucks. I understand there's a good reason & don't understand the internals, but I would say that as a user being able to work transparently with objects or strings (i.e. the behavior in b2-b4) was *extremely* nice. Anyway, thanks for clarification. Hans