# PHP5: hook cast_object handler in userspace

- Thread: https://externals.io/message/3697
- Original archive: https://news-web.php.net/php.internals/3697
- Started by Cristiano Duarte on 2003-08-02T22:50:01+00:00
- Messages: 12
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #3697 — Cristiano Duarte — 2003-08-02T22:50:01+00:00

URL: https://externals.io/message/3697#3697

Hi internals,

Is there a way to hook the cast_object handler in userspace ? What I want is
a default "to_string" method called when I do something like:

class my_object extends class_with_default_to_string_method {
    private $value = "Hello";
    public function to_string() { //overhiding default to_string wich prints
"Object id #n"
        return $this->value;
    }
}

$o = new my_object();
echo $o;

or:

$o = new xxx();
echo "My stringfied value is=$o";

Thanx,

Cristiano Duarte

---

## #3698 — Cristiano Duarte — 2003-08-02T23:00:10+00:00

URL: https://externals.io/message/3697#3698 · In reply to: #3697

Sorry guys,

> $o = new xxx();
should be $o = new my_object();

And if there is a way to hook into zend_standard_class (stdClass) what would
make all objects inherit the to_string method, it would be great !

Cristiano Duarte

"Cristiano Duarte" <cunha17@uol.com.br> escreveu na mensagem
news:20030802224959.58552.qmail@pb1.pair.com...
> Hi internals,
>
> Is there a way to hook the cast_object handler in userspace ? What I want
is
> a default "to_string" method called when I do something like:
>
> class my_object extends class_with_default_to_string_method {
>     private $value = "Hello";
>     public function to_string() { //overhiding default to_string wich
prints
> "Object id #n"
>         return $this->value;
>     }
> }
>
> $o = new my_object();
> echo $o;
>
> or:
>
> $o = new xxx();
> echo "My stringfied value is=$o";
>
> Thanx,
>
> Cristiano Duarte

---

## #3699 — Cristiano Duarte — 2003-08-03T03:33:25+00:00

URL: https://externals.io/message/3697#3699 · In reply to: #3698

I made a patch to the latest PHP5-CVS wich implements this hook. I think
it's useful to make a meaningful object stringfied value.

Can anyone verify it and maybe commit it to CVS ?

--- zend.c 2003-07-30 14:07:36.000000000 -0300
+++ zend.c.new 2003-08-03 00:27:43.000000000 -0300
@@ -227,10 +227,24 @@
    if (expr->value.obj.handlers->cast_object) {
     TSRMLS_FETCH();
     expr->value.obj.handlers->cast_object(expr, expr_copy, IS_STRING, 0
TSRMLS_CC);
    } else {
-    expr_copy->value.str.val = (char *) emalloc(sizeof("Object id #")-1 +
MAX_LENGTH_OF_LONG);
-    expr_copy->value.str.len = sprintf(expr_copy->value.str.val, "Object id
#%ld", (long)expr->value.obj.handle);
+      //call to_string method
+      zval *fname, *retval;
+      MAKE_STD_ZVAL(fname);
+      ZVAL_STRING(fname, "to_string", 1);
+      TSRMLS_FETCH();
+      if (call_user_function_ex(NULL, &expr, fname, &retval, 0, NULL, 0,
 `NULL` TSRMLS_CC) == SUCCESS) {
+         if (Z_TYPE_P(retval) != IS_STRING) {
+     convert_to_string(retval);
+         }
+         ZVAL_STRINGL(expr_copy, Z_STRVAL_P(retval), Z_STRLEN_P(retval),
1);
+         zval_ptr_dtor(&retval);
+      } else {
+                                     Z_STRVAL_P(expr_copy) = (char *)
emalloc(sizeof("Object id #")-1 + MAX_LENGTH_OF_LONG);
+                                     Z_STRLEN_P(expr_copy) =
sprintf(Z_STRVAL_P(expr_copy), "Object id #%ld",
(long)Z_OBJ_HANDLE_P(expr));
+      }
+      zval_ptr_dtor(&fname);
    }
 #if 0
    /* FIXME: This might break BC for some people */
    expr_copy->value.str.len = sizeof("Object")-1;


Thanx,

Cristiano Duarte.

"Cristiano Duarte" <cunha17@uol.com.br> escreveu na mensagem
news:20030802230007.65232.qmail@pb1.pair.com...
> Sorry guys,
>
> > […]
> should be $o = new my_object();
>
> And if there is a way to hook into zend_standard_class (stdClass) what
would
> make all objects inherit the to_string method, it would be great !
>
> Cristiano Duarte
>
> "Cristiano Duarte" <cunha17@uol.com.br> escreveu na mensagem
> news:20030802224959.58552.qmail@pb1.pair.com...
> > […]
want
> is
> > […]
> prints
> > […]

---

## #3703 — Sterling Hughes — 2003-08-03T06:57:40+00:00

URL: https://externals.io/message/3697#3703

So, being the author of the C-level cast_object(), I thought about
exposing this at one time.  I decided against it mainly because I needed
it for simplexml, and I didn't want an internals decision to be clouded
by userspace discussions (how's my whitespace btw?)

I really like the idea of PHP having an object interface that is
completely transparent.  It would be really nice if the language could
(preferably via interfaces), provide a way for userspace people to
design classes and objects that behave like base types.

Is this a bit magical?  Yes.
But its also the only reason I'd ever use objects.

If I need something to map to an external datasource, or an abstract
data type, objects are the most powerful container.  They allow for more
efficiency (fewer function calls), and a more elegant userspace
interface.   I think it would be really great if the PHP object model
contained all the necessary hooks so that something like simplexml could
be implemented in userspace.

-Sterling

Am Son, 2003-08-03 um 04.59 schrieb Marcus Börger:
> Hello Cristiano,
> 
> Sunday, August 3, 2003, 5:33:25 AM, you wrote:
> 
> CD> I made a patch to the latest PHP5-CVS wich implements this hook. I think
> CD> it's useful to make a meaningful object stringfied value.
> 
> CD> Can anyone verify it and maybe commit it to CVS ?
> 
> CD> --- zend.c 2003-07-30 14:07:36.000000000 -0300
> CD> +++ zend.c.new 2003-08-03 00:27:43.000000000 -0300
> CD> @@ -227,10 +227,24 @@
> CD>     if (expr->value.obj.handlers->cast_object) {
> CD>      TSRMLS_FETCH();
> CD>      expr->value.obj.handlers->cast_object(expr, expr_copy, IS_STRING, 0
> CD> TSRMLS_CC);
> CD>     } else {
> -    expr_copy->>value.str.val = (char *) emalloc(sizeof("Object id #")-1 +
> CD> MAX_LENGTH_OF_LONG);
> -    expr_copy->>value.str.len = sprintf(expr_copy->value.str.val, "Object id
> #%ld", (long)expr->>value.obj.handle);
> CD> +      //call to_string method
> CD> +      zval *fname, *retval;
> CD> +      MAKE_STD_ZVAL(fname);
> CD> +      ZVAL_STRING(fname, "to_string", 1);
> CD> +      TSRMLS_FETCH();
> CD> +      if (call_user_function_ex(NULL, &expr, fname, &retval, 0, NULL, 0,
> CD> `NULL` TSRMLS_CC) == SUCCESS) {
> CD> +         if (Z_TYPE_P(retval) != IS_STRING) {
> CD> +     convert_to_string(retval);
> CD> +         }
> CD> +         ZVAL_STRINGL(expr_copy, Z_STRVAL_P(retval), Z_STRLEN_P(retval),
> CD> 1);
> CD> +         zval_ptr_dtor(&retval);
> CD> +      } else {
> CD> +                                     Z_STRVAL_P(expr_copy) = (char *)
> CD> emalloc(sizeof("Object id #")-1 + MAX_LENGTH_OF_LONG);
> CD> +                                     Z_STRLEN_P(expr_copy) =
> CD> sprintf(Z_STRVAL_P(expr_copy), "Object id #%ld",
> CD> (long)Z_OBJ_HANDLE_P(expr));
> CD> +      }
> CD> +      zval_ptr_dtor(&fname);
> CD>     }
> CD>  #if 0
> CD>     /* FIXME: This might break BC for some people */
> CD>     expr_copy->value.str.len = sizeof("Object")-1;
> 
> 
> CD> Thanx,
> 
> CD> Cristiano Duarte.
> 
> CD> "Cristiano Duarte" <cunha17@uol.com.br> escreveu na mensagem
> CD> news:20030802230007.65232.qmail@pb1.pair.com...
> > […]
> CD> would
> > […]
> CD> want
> > […]
> 
> 
> 
> 
> The patch doesn't compile (always use confugure --enable-maintainer-zts).
> Then you assume that every class has a function to_string(), this is not what
> we want.
> 
> -- 
> Best regards,
>  Marcus                            mailto:helly@php.net
-- 
UNIX was not designed to stop you from doing stupid things, because that
would also stop you from doing clever things. 
  - Doug Gwyn

---

## #3715 — Cristiano Duarte — 2003-08-04T02:45:20+00:00

URL: https://externals.io/message/3697#3715

Hello Marcus,

> CD> switch/case removed and patch attached. Is it ok?
> CD> Should the method be named "to_string()", "tostring()" or
"__tostring()" ?
> CD> Do you commit it to CVS ?
>
> No. Last Problem i see is that even when to_string() is available the
default
> behavior can get called that seems wrong. If that function doesn't return
a
> string it's an error and it shouldn't fall back to default in that case.

Do you think it's an error even if the value returned got cast to string ?
I don't know how to throw an error/exception from inside the core of Zend2.
I have some code to throw an exception/error from extensions...

> However with that last change the thing would be ok from my point of view.
> Perhaps you could also add an interface for that function as sterling once
> suggested. But still you need to discuss this with the rest of the ppl
here.
> Because eventually we might want to do it with overloadable object
handlers.

I modified the code to just call to_string if the object implements the
"printable" interface.
But I don't know how and where to register the interface in ZE2. Are there
any interfaces registered inside ZE2? I cound't find any...

If you could point me some code to dig...

Cristiano Duarte

---

## #3729 — Alan Knowles — 2003-08-05T06:43:53+00:00

URL: https://externals.io/message/3697#3729

> switch/case removed and patch attached. Is it ok?
> Should the method be named "to_string()", "tostring()" or "__tostring()" ?
According to the current Coding Standard document.. it should be 
toString() : even though php is not Case-sensitive:)..

Would be nice to see this work..

Regards
Alan

> Do you commit it to CVS ?
> 
> Cristiano Duarte
> 
> 
> 


-- 
Can you help out?
Need Consulting Services or Know of a Job?
http://www.akbkhome.com

---

## #3742 — Cristiano Duarte — 2003-08-05T23:23:15+00:00

URL: https://externals.io/message/3697#3742 · In reply to: #3729

Hi all,

SK> Maybe it will be better to have this method in all classes and define
SK> default behavior such as existing ( string )$object cast?
I guess that using an interface is better. But if the guys here think
different I would revert to the patch with no interfaces.

AK> According to the current Coding Standard document.. it should be
AK> toString() : even though php is not Case-sensitive:)..
What about __construct, __destruct and __clone ? Shouldn't it be named
__to_string() or __tostring() ?

AK> Would be nice to see this work..
In fact, this does work. The method is called to_string().

Two questions:
1) I can't figure out a better name for the interface. Any ideas ?
2) Should all objects implent this method like __construct, __destruct and
__clone or should it be left to the user to decide whether the object
implements the printable interface or not.(IMHO a prefer the second)

Cristiano Duarte.

"Alan Knowles" <alan@akbkhome.com> escreveu na mensagem
news:3F2F5229.5070004@akbkhome.com...
>
> > […]
?
> According to the current Coding Standard document.. it should be
> toString() : even though php is not Case-sensitive:)..
>
> Would be nice to see this work..
>
> Regards
> Alan
>
> > […]
>
>
> --
> Can you help out?
> Need Consulting Services or Know of a Job?
> http://www.akbkhome.com

---

## #3749 — Alan Knowles — 2003-08-06T00:15:50+00:00

URL: https://externals.io/message/3697#3749 · In reply to: #3742

>AK> According to the current Coding Standard document.. it should be
>AK> toString() : even though php is not Case-sensitive:)..
>What about __construct, __destruct and __clone ? 
>
these are built in. - and done to avoid conflicts.

>Shouldn't it be named
>__to_string() or __tostring() ?
>
since you implicitly make this available  by adding an interface 
Morphable?? or soemthing, - toString() is ok..
I think it's alot better to make it available via an interface.. - It at 
least give you some chance of working out why it works as it does..

It would be nice to hear some noise from Zeev and Andi on this :)

Regards
Alan

---

## #3750 — Cristiano Duarte — 2003-08-06T02:08:42+00:00

URL: https://externals.io/message/3697#3750 · In reply to: #3749

"Alan Knowles" <alan@akbkhome.com> escreveu na mensagem
news:3F3048B6.2060903@akbkhome.com...
>
> > […]
AK> these are built in. - and done to avoid conflicts.

All right.

> > […]
AK> since you implicitly make this available  by adding an interface
AK> Morphable?? or soemthing, - toString() is ok..
AK> I think it's alot better to make it available via an interface.. - It at
AK> least give you some chance of working out why it works as it does..

Ok. New patch included.

AK> It would be nice to hear some noise from Zeev and Andi on this :)

I agree.


Regards,
Cristiano Duarte

---

## #3753 — Simeon Koptelov — 2003-08-06T08:07:36+00:00

URL: https://externals.io/message/3697#3753 · In reply to: #3742

Hello Cristiano,

Here's why i think that interface is not good solution.

We need the toString method like java's one to
safely assume that _every_ object has the string representation. This
means we can say $obj1->toString() and $obj2->toString() and don't
care if $obj1 and $obj2 do support this method. In fact we _already_
have this functionality in ( string )$obj cast -- it's
applicable to any object, doesn't it?. All we need is to formalize
this cast in OOP manner. Interface is only the way to describe what class
can do. If every class can provide it's string representation why should you
implement some interface?

It's only my $.20 though.

-- 
Best regards,
 Simeon                            mailto:xi@newmail.ru

---

## #3761 — Cristiano Duarte — 2003-08-06T13:19:34+00:00

URL: https://externals.io/message/3697#3761 · In reply to: #3753

Simeon Koptelov wrote:
> Hello Cristiano,
> 
> Here's why i think that interface is not good solution.
> 
> We need the toString method like java's one to
> safely assume that _every_ object has the string representation. This
> means we can say $obj1->toString() and $obj2->toString() and don't
> care if $obj1 and $obj2 do support this method. In fact we _already_
> have this functionality in ( string )$obj cast -- it's
> applicable to any object, doesn't it?. All we need is to formalize
> this cast in OOP manner. Interface is only the way to describe what class
> can do. If every class can provide it's string representation why should you
> implement some interface?
> 
> It's only my $.20 though.
> 

Maybe you're right.
I can move the code away from the "cast" function and create a toString 
method on the "Object" class wich returns "Object id #n".
Let's see what the others think about it...


Cristiano Duarte

---

## #3839 — Cristiano Duarte — 2003-08-09T20:48:22+00:00

URL: https://externals.io/message/3697#3839

Hello Marcus,

Did you think of a better interface name instead of "Printable" ?
Do you think Zeev or Andi will accept this patch ?

Cristiano.
