# __toString(), __toArray()

- Thread: https://externals.io/message/46643
- Original archive: https://news-web.php.net/php.internals/46643
- Started by Clint Priest on 2010-01-11T18:31:33+00:00
- Messages: 18
- 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

---

## #46643 — Clint Priest — 2010-01-11T18:31:33+00:00

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

I know there's been requests to add a __toArray() and most of the 
arguments against it is that there are too many magic functions already. 
  I just thought I'd propose an alternative that would satisfy all of them.

Why not a __cast($Type) magic function?

---

## #46648 — Etienne Kneuss — 2010-01-12T01:29:24+00:00

URL: https://externals.io/message/46643#46648 · In reply to: #46643

Hello,


> I know there's been requests to add a __toArray() and most of the arguments
> against it is that there are too many magic functions already.  I just
> thought I'd propose an alternative that would satisfy all of them.
>
> Why not a __cast($Type) magic function?

I'd advance two reasons against this idea:

1) It's more self-explanatory to explicitly call the appropriate
converting method, enough with implicit madness!

2) For some operations, you'd have to know the types in advance before
knowing what operations needs to be performed:

$obj1 + 2;

Now what __cast should be called? Int? Float?

Also, what about $obj1 + $obj2: Int? Float? Array?

Another example: str_replace($obj1, "bar", "foo"); what to call?
__toString or __toArray? str_replace accepts both.

IMHO it would only make sense to invoke methods on explicit casts
only, otherwise it will just be a mess with PHP's current type
juggling. But, as we seen with __toString, limiting the field of
application was annoying (and it was later extended to nearly all
string usages).

So, what will it be? Inconsistent and Confusing or Limited and Annoying?

>
> --
> 
> 
>
>



-- 
Etienne Kneuss
http://www.colder.ch

---

## #46649 — Stanislav Malyshev — 2010-01-12T01:46:53+00:00

URL: https://externals.io/message/46643#46649 · In reply to: #46648

Hi!

> > […]

The interesting thing is that in the engine the object handler is actually:

typedef int (*zend_object_cast_t)(zval *readobj, zval *retval, int type 
TSRMLS_DC);

i.e. the handler is already generic, but implementation API isn't - 
standard engine handler supports only IS_STRING (and IS_BOOL is a funny 
way - objects are always true). In other words, extensions already can 
do this, PHP programmer can't.

> 1) It's more self-explanatory to explicitly call the appropriate
> converting method, enough with implicit madness!

This is probably the reason why the above was done - conversion to the 
string representation is a very frequent action (especially in the Web 
world where everything ends up being in the text page anyway ;) while 
conversion to numeric types is very special case and very ambiguous, as 
Etienne noted, and conversion to an array is also rather special case (a 
lot of cases where array-like syntax is called for are served by 
ArrayAccess).
-- 
Stanislav Malyshev, Zend Software Architect
stas@zend.com   http://www.zend.com/
(408)253-8829   MSN: stas@zend.com

---

## #46650 — Clint Priest — 2010-01-12T03:17:53+00:00

URL: https://externals.io/message/46643#46650 · In reply to: #46648

Etienne Kneuss wrote:
> Hello,
> 
> 
> > […]
> 
> I'd advance two reasons against this idea:
> 
> 1) It's more self-explanatory to explicitly call the appropriate
> converting method, enough with implicit madness!
> 
> 2) For some operations, you'd have to know the types in advance before
> knowing what operations needs to be performed:
> 
> $obj1 + 2;
> 
> Now what __cast should be called? Int? Float?

Wouldn't it make sense to be an integer since its being added to an integer?

> 
> Also, what about $obj1 + $obj2: Int? Float? Array?

This is where operator over-loading would be useful however perhaps only 
explicit casts would make sense here.

> 
> Another example: str_replace($obj1, "bar", "foo"); what to call?
> __toString or __toArray? str_replace accepts both.

This is an interesting situation, could be resolved by attempting a 
__cast('array') followed by a __cast('string') if the first call was 
rejected (false, exception or something).

> 
> IMHO it would only make sense to invoke methods on explicit casts
> only, otherwise it will just be a mess with PHP's current type
> juggling. But, as we seen with __toString, limiting the field of
> application was annoying (and it was later extended to nearly all
> string usages).

I would agree with this as well, only called during explicit casts.

> 
> So, what will it be? Inconsistent and Confusing or Limited and Annoying?
> 

One other alternative, probably not as easy would be to pass multiple 
types to cast, much the way the Accepts: HTTP header does, providing a 
list of possible cast types, in the preferred order.

One could even implement an interface such as:

interface Castable {
    function GetCastableTypes();
}

or some such.

---

## #46651 — mm w — 2010-01-12T03:32:08+00:00

URL: https://externals.io/message/46643#46651 · In reply to: #46650

cast is not needed in PHP

i 'd rather be more interesting in

class Obj {
     function __catch($data, $type) {
            //$type [ static_method, method, get_property, set_property]
            if (observed &&  $type == set_property && somevalueIsObserved) {
                  $observer->notify("somevalue::valueWillChanged");
                  $this->somevalue = $data['somevalue'];
                  $observer->notify("somevalue::valueDidChanged");
            } else {
                  continue__call();
            }
     }
}


>
> Etienne Kneuss wrote:
> > […]
>
> Wouldn't it make sense to be an integer since its being added to an integer?
>
> > […]
>
> This is where operator over-loading would be useful however perhaps only
> explicit casts would make sense here.
>
> > […]
>
> This is an interesting situation, could be resolved by attempting a
> __cast('array') followed by a __cast('string') if the first call was
> rejected (false, exception or something).
>
> > […]
>
> I would agree with this as well, only called during explicit casts.
>
> > […]
>
> One other alternative, probably not as easy would be to pass multiple types
> to cast, much the way the Accepts: HTTP header does, providing a list of
> possible cast types, in the preferred order.
>
> One could even implement an interface such as:
>
> interface Castable {
>   function GetCastableTypes();
> }
>
> or some such.

---

## #46659 — Chris Stockton — 2010-01-12T22:40:58+00:00

URL: https://externals.io/message/46643#46659 · In reply to: #46651

Hello,


> cast is not needed in PHP
>
> i 'd rather be more interesting in
>
> class Obj {
>     function __catch($data, $type) {
>            //$type [ static_method, method, get_property, set_property]
>            if (observed &&  $type == set_property && somevalueIsObserved) {
>                  $observer->notify("somevalue::valueWillChanged");
>                  $this->somevalue = $data['somevalue'];
>                  $observer->notify("somevalue::valueDidChanged");
>            } else {
>                  continue__call();
>            }
>     }
> }

What? ...

> > […]

I beleive adding a __cast(string $type) would be a useful feature for
me, very often I have a toArray method defined. I agree with you that
due to unexpected edge cases with operator precedence and general type
juggling that __cast should only be called on explicit (cast).

I.E.:
class Int { public function __cast($type) { return 'int' == $type ? 15 : 0; } }
$r = new Int;

var_dump($r + 1); // 2
var_dump((int) $r + 1); // 16
var_dump((bool) $r + 1); // 1

---

## #46664 — mm w — 2010-01-13T02:09:25+00:00

URL: https://externals.io/message/46643#46664 · In reply to: #46659

don't worry it's only for people who are working with MVC and
RootObject structure, there is too much magics already and __cast is
not needed at all,
as we cannot monkey patch to add an observer on itself, a nice
solution should have a catchable object so __catch any calls

function __catch($data, $type) {
    if (method == $type) {
         if (data[selector] = 'setValue' && observedValueForKeyPath) {
             $this->_setValue(($data['arg']);
             return;
         }
    }
    continue_natural_call();
}

we could imagine to have a root-object-built-in-class that is
naturally observable, or a root classObject at all, anyway it's only
something for people who are doing OO programming,
so don't worry

On Tue, Jan 12, 2010 at 2:40 PM, Chris Stockton
<chrisstocktonaz@gmail.com> wrote:
> Hello,
>
> 
> > […]
>
> What? ...
>
> > […]
>
> I beleive adding a __cast(string $type) would be a useful feature for
> me, very often I have a toArray method defined. I agree with you that
> due to unexpected edge cases with operator precedence and general type
> juggling that __cast should only be called on explicit (cast).
>
> I.E.:
> class Int { public function __cast($type) { return 'int' == $type ? 15 : 0; } }
> $r = new Int;
>
> var_dump($r + 1); // 2
> var_dump((int) $r + 1); // 16
> var_dump((bool) $r + 1); // 1

---

## #46665 — Eddie Drapkin — 2010-01-13T02:10:59+00:00

URL: https://externals.io/message/46643#46665 · In reply to: #46664

How does this have *anything* to do with the discussion at hand?


> don't worry it's only for people who are working with MVC and
> RootObject structure, there is too much magics already and __cast is
> not needed at all,
> as we cannot monkey patch to add an observer on itself, a nice
> solution should have a catchable object so __catch any calls
>
> function __catch($data, $type) {
>    if (method == $type) {
>         if (data[selector] = 'setValue' && observedValueForKeyPath) {
>             $this->_setValue(($data['arg']);
>             return;
>         }
>    }
>    continue_natural_call();
> }
>
> we could imagine to have a root-object-built-in-class that is
> naturally observable, or a root classObject at all, anyway it's only
> something for people who are doing OO programming,
> so don't worry
>
> On Tue, Jan 12, 2010 at 2:40 PM, Chris Stockton
> <chrisstocktonaz@gmail.com> wrote:
> > […]

---

## #46666 — mm w — 2010-01-13T02:11:51+00:00

URL: https://externals.io/message/46643#46666 · In reply to: #46665

the multiplication of magic, the pointed point, need to read more carefully


> How does this have *anything* to do with the discussion at hand?
>
> 
> > […]

---

## #46667 — Eddie Drapkin — 2010-01-13T02:29:41+00:00

URL: https://externals.io/message/46643#46667 · In reply to: #46666

What you're proposing is just forcing __call, _callStatic, __get and
__set into a single method, which does nothing to reduce the amount of
magic, only obfuscate it.  And it certainly offers no alternative to
"__cast", at least not that I can see.


> the multiplication of magic, the pointed point, need to read more carefully
>
> 
> > […]

---

## #46668 — mm w — 2010-01-13T02:45:45+00:00

URL: https://externals.io/message/46643#46668 · In reply to: #46667

I am not forcing anything, it's already there, that's definitely a
more useful magic, if people would add a new one, __cast is not
critical, catchable objects are __catch even if exists, so my point I
'd rather see useful requests than a unseful one e.g __cast

from my perspective __toString and __toArray , __callStatic should be
removed  __callStatic  is definitly a mistake.




> What you're proposing is just forcing __call, _callStatic, __get and
> __set into a single method, which does nothing to reduce the amount of
> magic, only obfuscate it.  And it certainly offers no alternative to
> "__cast", at least not that I can see.
>
> 
> > […]

---

## #46669 — Clint Priest — 2010-01-13T02:59:41+00:00

URL: https://externals.io/message/46643#46669 · In reply to: #46667

Eddie Drapkin wrote:
> What you're proposing is just forcing __call, _callStatic, __get and
> __set into a single method, which does nothing to reduce the amount of
> magic, only obfuscate it.  And it certainly offers no alternative to
> "__cast", at least not that I can see.

I agree, moving all magic to a single function doesn't help the 
situation at all, it simply complicates it.

All this talk of "too many magic functions" is a little comical, its all 
trying to overcome operator overloading type functionality in other 
languages.

__get()/__set() would be equivalent to getters/setters supported by the 
c# language

__toString(), __toArray() would be equivalent to operator String() in 
c++ ( if I remember correctly )

I would definitely love to be able to, at the very least, cast an object 
to an array but I figured a more general purpose __cast() would be most 
beneficial to all.

I think the ambiguity question for some functions accepting mixed as a 
parameter type could be solved in aforementioned ways.

> 
> > […]

---

## #46672 — mm w — 2010-01-13T04:09:48+00:00

URL: https://externals.io/message/46643#46672 · In reply to: #46669

I don't move any magics,I am worried about your knowledge of php,
there's people to give you money ? weird, set get call are only call
when something doesn't exist catch or catch-able concept is to be able
to catch any existing calls no the dynamic ones.



>
>
> Eddie Drapkin wrote:
> > […]
>
> I agree, moving all magic to a single function doesn't help the situation at
> all, it simply complicates it.
>
> All this talk of "too many magic functions" is a little comical, its all
> trying to overcome operator overloading type functionality in other
> languages.
>
> __get()/__set() would be equivalent to getters/setters supported by the c#
> language
>
> __toString(), __toArray() would be equivalent to operator String() in c++ (
> if I remember correctly )
>
> I would definitely love to be able to, at the very least, cast an object to
> an array but I figured a more general purpose __cast() would be most
> beneficial to all.
>
> I think the ambiguity question for some functions accepting mixed as a
> parameter type could be solved in aforementioned ways.
>
> > […]

---

## #46673 — Chris Stockton — 2010-01-13T05:50:28+00:00

URL: https://externals.io/message/46643#46673 · In reply to: #46672

I don't move any magics, I'm worried your knowledge of social skills? Theirs
people be your friends? Weird



I don't move any magics,I am worried about your knowledge of php,
there's people to give you money ? weird, set get call are only call
when something doesn't exist catch or catch-able concept is to be able
to catch any existing calls no the dynamic ones.


> > […]
--

 To unsubscribe, visit:
http://www.php.net/unsub...

---

## #46674 — mm w — 2010-01-13T07:02:19+00:00

URL: https://externals.io/message/46643#46674 · In reply to: #46673

:-D, without  any magic,  I am sorry if I hurt you I though you were
tougher than a cookie, don't worry about my friends I have plenty on
face-cooked, but for God Sake I am still eating alone at noon 8-)


On Tue, Jan 12, 2010 at 9:50 PM, Chris Stockton
<chrisstocktonaz@gmail.com> wrote:
> I don't move any magics, I'm worried your knowledge of social skills? Theirs
> people be your friends? Weird
>
> 
>
> I don't move any magics,I am worried about your knowledge of php,
> there's people to give you money ? weird, set get call are only call
> when something doesn't exist catch or catch-able concept is to be able
> to catch any existing calls no the dynamic ones.
>
> 
> > […]
>
> --
>
>  To unsubscribe, visit:
> http://www.php.net/unsub...

---

## #46676 — Etienne Kneuss — 2010-01-13T10:12:05+00:00

URL: https://externals.io/message/46643#46676 · In reply to: #46659

Hello,

On Tue, Jan 12, 2010 at 11:40 PM, Chris Stockton
<chrisstocktonaz@gmail.com> wrote:
> Hello,
>
> 
> > […]
>
> What? ...
>
> > […]
>
> I beleive adding a __cast(string $type) would be a useful feature for
> me, very often I have a toArray method defined. I agree with you that
> due to unexpected edge cases with operator precedence and general type
> juggling that __cast should only be called on explicit (cast).
>
> I.E.:
> class Int { public function __cast($type) { return 'int' == $type ? 15 : 0; } }
> $r = new Int;

This is an exemple where __cast would be very wrong. At the very
least, it should return a value that is an inhabitant of the requested
type! Do you really want (bool)new Int() to be Int 0?

as a result, you have three solutions:
1) have the engine issue an error in case the return value is not compatible
2) provide a return value for every possible types requested
3) throw an exception in case the cast is not handled

In the end, it looks way more complicated/magic than _simply_ defining
a toArray method that is used whenever you need an object to be an
array. You need an explicit cast anyway, so it's (array)$obj vs
$obj->toArray().

>
> var_dump($r + 1); // 2
> var_dump((int) $r + 1); // 16
> var_dump((bool) $r + 1); // 1
>
> --
> 
> 
>
>



-- 
Etienne Kneuss
http://www.colder.ch

---

## #46677 — Ionut G. Stan — 2010-01-13T10:22:35+00:00

URL: https://externals.io/message/46643#46677 · In reply to: #46672

It appears that, mm w is talking about some aspect oriented feature.

I would welcome a magic method that would intercept calls/access to 
existing methods/properties (not only inaccessible ones), in the same 
sense that __getattribute__ works in Python for example IIRC. It may 
also be a good time to unify properties and types in PHP (we see a lot 
of problems with lambdas assigned to object properties).

But... that's certainly another topic.


> I don't move any magics,I am worried about your knowledge of php,
> there's people to give you money ? weird, set get call are only call
> when something doesn't exist catch or catch-able concept is to be able
> to catch any existing calls no the dynamic ones.
>
>
> 
> > […]
>

-- 
Ionut G. Stan
I'm under construction  |  http://blog.igstan.ro/

---

## #46684 — Clint Priest — 2010-01-13T13:01:19+00:00

URL: https://externals.io/message/46643#46684 · In reply to: #46676

Etienne Kneuss wrote:
> Hello,
> 
> On Tue, Jan 12, 2010 at 11:40 PM, Chris Stockton
> <chrisstocktonaz@gmail.com> wrote:
> > […]
> 
> This is an exemple where __cast would be very wrong. At the very
> least, it should return a value that is an inhabitant of the requested
> type! Do you really want (bool)new Int() to be Int 0?
> 
> as a result, you have three solutions:
> 1) have the engine issue an error in case the return value is not compatible
> 2) provide a return value for every possible types requested
> 3) throw an exception in case the cast is not handled
> 
> In the end, it looks way more complicated/magic than _simply_ defining
> a toArray method that is used whenever you need an object to be an
> array. You need an explicit cast anyway, so it's (array)$obj vs
> $obj->toArray().

One difference between these two possibilities is that consumers of an 
array parameter could consume an object castable to an array whereas it 
would need to have knowledge that ->toArray() exists in the second scenario.

> 
> > […]
