Hi,
I've got an idea for adding common way to convert array from object:
ArraySerializable interface and to allow the changing of existing
array conversion mechanism.
As an example of this change, consider the following code-snippet:
$person = new StdClass();
$person->name = "John";
$phone = new StdClass();
$phone->number = "12345";
$person->phone = $phone;
var_dump((array)$person);
#array(2) {
# ["name"]=>
# string(4) "John"
# ["phone"]=>
# object(stdClass)#2 (1) {
# ["number"]=>
# string(5) "12345"
# }
#}
Currently, the implicit object to array conversion does not work
recursively. This propose changes object to array conversion behaviour
which implements ArraySerializable interface. specifically
ArraySerializable::__toArray method overrides current (array) cast.
interface ArraySerializable
{
/** @return array */
public function __toArray();
}
ArraySerializable interface provides common way to convert to array
from object. also impose conversion rule.
- __toArray() returning value excepts an array and It values only
accepts primitive type. (long, double, string and array)- do cast to array operation when the value contains object which
implements ArraySerializable interface - otherwise, raise RuntimeException.
- do cast to array operation when the value contains object which
- __toArray() method calls implicitly when cast to array from object.
This feature improves object to portable format (like json) conversion
mechanism.
rough propose document and patch are here:
https://gist.github.com/chobie/7890899
I want to get feedback about this propose. If I get a good response
I'll investigate potential issues and improve rfc and patch.
Thanks,
Shuhei
I am personally (currently) relying on the approach where array conversion
gives me the values of the various properties as objects (when they are
objects), so I wouldn't like another magic operator in there (to deal
with/workaround).
Wondering why this approach would be better than doing a recursive array
map iteration.
Pardon my naive and inelegant way of dealing with maps (see the running
example at http://3v4l.org/ZOodL ):
class ObjectToArrayConverter
{
/**
* @param mixed $value
*
* @raturn array
*/
public static function toArray($value)
{
if (! (is_object($value) || is_array($value))) {
return $value;
}
if (is_object($value) && method_exists($value, '__toArray')) {
return $value->__toArray();
}
return array_map(__METHOD__, (array) $value);
}
}
Marco Pivetta
Hi,
I've got an idea for adding common way to convert array from object:
ArraySerializable interface and to allow the changing of existing
array conversion mechanism.
As an example of this change, consider the following code-snippet:$person = new StdClass(); $person->name = "John"; $phone = new StdClass(); $phone->number = "12345"; $person->phone = $phone; var_dump((array)$person); #array(2) { # ["name"]=> # string(4) "John" # ["phone"]=> # object(stdClass)#2 (1) { # ["number"]=> # string(5) "12345" # } #}
Currently, the implicit object to array conversion does not work
recursively. This propose changes object to array conversion behaviour
which implements ArraySerializable interface. specifically
ArraySerializable::__toArray method overrides current (array) cast.interface ArraySerializable { /** @return array */ public function __toArray(); }
ArraySerializable interface provides common way to convert to array
from object. also impose conversion rule.
- __toArray() returning value excepts an array and It values only
accepts primitive type. (long, double, string and array)
- do cast to array operation when the value contains object which
implements ArraySerializable interface- otherwise, raise RuntimeException.
- __toArray() method calls implicitly when cast to array from object.
This feature improves object to portable format (like json) conversion
mechanism.rough propose document and patch are here:
https://gist.github.com/chobie/7890899I want to get feedback about this propose. If I get a good response
I'll investigate potential issues and improve rfc and patch.Thanks,
Shuhei
On 11 December 2013 02:36, Marco Pivetta ocramius@gmail.com wrote:class
ObjectToArrayConverter
{
/**
* @param mixed $value
*
* @raturn array
*/
public static function toArray($value)
{
if (! (is_object($value) || is_array($value))) {
return $value;
}if (is_object($value) && method_exists($value, '__toArray')) { return $value->__toArray(); } return array_map(__METHOD__, (array) $value); }
}
Note: I didn't consider the case of cyclic references.
Marco Pivetta
2013/12/11 Marco Pivetta ocramius@gmail.com:
I am personally (currently) relying on the approach where array conversion
gives me the values of the various properties as objects (when they are
objects), so I wouldn't like another magic operator in there (to deal
with/workaround).
Wondering why this approach would be better than doing a recursive array map
iteration.Pardon my naive and inelegant way of dealing with maps (see the running
example at http://3v4l.org/ZOodL ):
Yea, I also use same approach. let me explain my story:
I'm working at web gaming company and maintain many models which are
complex and nested classes.( like Player, Inventory, Item... )
Currently, We use toArray
or whatever method when passing those
variables to web browser.
Issue with this approach:
Developer have to consider returning values which handle recursively,
removing unwanted values...etc.
Also, Unfortunately this approach is company specific. We'd like to
follow common way to cast array from object.
The pros of proposed approach:
- Easy to convert to array from complex object.
returning value only contains primitive types (long, double, string,
array). and call__toArray
method recursively when the value
contains object.
I think this rule will reduce production costs. just define
__toArray method and wanted returning values. don't care about other
things.
I'm actually wondering about the opposite case.
What would I have to do to have the previous behavior working on anArraySerializable
instance (basically ignore__toArray()
for one particular cast)?
I don't want to go the reflection way :-)
I'm curious about your story. What king of work do you do?
This kind of proposes regards coding standards. It's okay to propose which part.
2013/12/11 Marco Pivetta ocramius@gmail.com:
I'm actually wondering about the opposite case.
What would I have to do to have the previous behavior working on an
ArraySerializable
instance (basically ignore__toArray()
for one
particular cast)?
I don't want to go the reflection way :-)I'm curious about your story. What king of work do you do?
There are quite a lot of cases where array cast behavior is currently
something we rely on (to avoid reflection). Here's two that come into my
mind:
-
Using
__sleep()
and returning array keys for parent classes'
properties:public function __sleep()
{
return array_keys((array) $this); // handles the "\0*\0" or
"\0ClassName\0" properties
} -
Relying on
(array)
casting returning all property names all the time -
Some stuff I've been working about converting objects to arrays to
objects (GeneratedHydrator)
Those are some of the bc breaks that I have on top of my mind.
I'd rather prefer having userland implementations as I mentioned before
(since it's possible). Casting to (array)
actually solves more complex
problems, while solving the problem of extracting data is fairly simple
Marco Pivetta
2013/12/13 Marco Pivetta ocramius@gmail.com:
I'd rather prefer having userland implementations as I mentioned before
(since it's possible). Casting to(array)
actually solves more complex
problems, while solving the problem of extracting data is fairly simple
Thanks, I understand your use case. Surely, casting to (array)
is
faster than ReflectionProperty.
I just came up with adding ObjectHydrator extension is also
interesting solution on your case.
Okay, I'll stop this propose at this time. As there is similar rfc and
that status is in draft: https://wiki.php.net/rfc/object_cast_to_types
I'm sorry about my poor research.
Thanks for the feedbacks.
Shuhei
I think this would be a great feature. PHP already casts objects to arrays, so being able to customize that behavior would be really helpful.
For example, Guzzle uses a similar interface to handle marshaling objects to associative arrays when serializing requests.
-Michael
Hi,
I've got an idea for adding common way to convert array from object:
ArraySerializable interface and to allow the changing of existing
array conversion mechanism.
As an example of this change, consider the following code-snippet:$person = new StdClass();
$person->name = "John";
$phone = new StdClass();
$phone->number = "12345";
$person->phone = $phone;var_dump((array)$person);
#array(2) {["name"]=>
string(4) "John"
["phone"]=>
object(stdClass)#2 (1) {
["number"]=>
string(5) "12345"
}
#}
Currently, the implicit object to array conversion does not work
recursively. This propose changes object to array conversion behaviour
which implements ArraySerializable interface. specifically
ArraySerializable::__toArray method overrides current (array) cast.interface ArraySerializable
{
/** @return array */
public function __toArray();
}ArraySerializable interface provides common way to convert to array
from object. also impose conversion rule.
- __toArray() returning value excepts an array and It values only
accepts primitive type. (long, double, string and array)
- do cast to array operation when the value contains object which
implements ArraySerializable interface- otherwise, raise RuntimeException.
- __toArray() method calls implicitly when cast to array from object.
This feature improves object to portable format (like json) conversion
mechanism.rough propose document and patch are here:
https://gist.github.com/chobie/7890899I want to get feedback about this propose. If I get a good response
I'll investigate potential issues and improve rfc and patch.Thanks,
Shuhei
I think this would be a great feature. PHP already casts objects to
arrays, so being able to customize that behavior would be really helpful.
I'm actually wondering about the opposite case.
What would I have to do to have the previous behavior working on an
ArraySerializable
instance (basically ignore __toArray()
for one
particular cast)?
I don't want to go the reflection way :-)
Marco Pivetta
> Hi,
>
> I've got an idea for adding common way to convert array from object:
> ArraySerializable interface and to allow the changing of existing
> array conversion mechanism.
...
Currently, the implicit object to array conversion does not work
> recursively. This propose changes object to array conversion behaviour
> which implements ArraySerializable interface. specifically
> ArraySerializable::__toArray method overrides current (array) cast.
>
> interface ArraySerializable
> {
> /** @return array */
> public function __toArray();
> }
>
I have no problems with the proposal in general, however did you see there
is an RFC already related to this (
https://wiki.php.net/rfc/object_cast_to_types) that has a patch you might
like to reference?
I would still like to see the full suite of type-conversion magic methods,
I don't see an argument for implementing one and not the others.
Not sure if this should come with an interface, for example __toString()
does not come with a StringSerializable interface.
Perhaps __toArray() / __toString / __toWhatever should all be available
without an interface, but also have interfaces that wrap them for the sake
of typehinting (which means adding an interface for __toString)
I have no problems with the proposal in general, however did you see there
is an RFC already related to this
(https://wiki.php.net/rfc/object_cast_to_types) that has a patch you might
like to reference?
Ah, I'm sorry. I didn't read the rfc and discussions when I sent email.
that rfc and patch seems fine. but little bit big changes.
Not sure if this should come with an interface, for example __toString()
does not come with a StringSerializable interface.Perhaps __toArray() / __toString / __toWhatever should all be available
without an interface, but also have interfaces that wrap them for the sake
of typehinting (which means adding an interface for __toString)
I agree your opinion. casting magic method shouldn't have interface.
At this time. I referenced JsonSerialize but it's too much in this case.