FAQ
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/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

Search Discussions

  • Marco Pivetta at Dec 11, 2013 at 1:37 am
    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

    http://twitter.com/Ocramius

    http://ocramius.github.com/

    On 11 December 2013 02:23, chobie wrote:

    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/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

    --
    PHP Internals - PHP Runtime Development Mailing List
    To unsubscribe, visit: http://www.php.net/unsub.php
  • Marco Pivetta at Dec 11, 2013 at 1:38 am
    On 11 December 2013 02:36, Marco Pivetta 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

    http://twitter.com/Ocramius

    http://ocramius.github.com/
  • Chobie at Dec 11, 2013 at 3:29 pm

    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 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?

    This kind of proposes regards coding standards. It's okay to propose which part.
  • Marco Pivetta at Dec 12, 2013 at 11:20 pm

    On 11 December 2013 16:29, chobie wrote:

    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

    http://twitter.com/Ocramius

    http://ocramius.github.com/
  • Chobie at Dec 16, 2013 at 7:19 am

    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
  • Michael Dowling at Dec 11, 2013 at 2:37 am
    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
    On Dec 10, 2013, at 5:23 PM, chobie wrote:

    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/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

    --
    PHP Internals - PHP Runtime Development Mailing List
    To unsubscribe, visit: http://www.php.net/unsub.php
  • Marco Pivetta at Dec 11, 2013 at 2:43 am

    On 11 December 2013 03:37, Michael Dowling wrote:

    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

    http://twitter.com/Ocramius

    http://ocramius.github.com/
  • Leigh at Dec 11, 2013 at 8:18 am

    On 11 December 2013 01:23, chobie wrote:

    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)
  • Chobie at Dec 11, 2013 at 3:39 pm

    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.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupphp-internals @
categoriesphp
postedDec 11, '13 at 1:23a
activeDec 16, '13 at 7:19a
posts10
users4
websitephp.net

People

Translate

site design / logo © 2017 Grokbase