0

I'm trying to flatten this array such that the child is the same level as the parent. I've tried solutions from other StackOverflow questions like this and this, but to no avail. Any ideas?

(int) 3 => object() {

    "new" => false,
    "properties" => [
        "id" => (int) 180,
        "name" => "Herp de Derp",
        "parent_id" => (int) 169,
        "lft" => (int) 16,
        "rght" => (int) 19,
        "children" => [
            (int) 0 => object(App\Model\Entity\Team) {

                "new" => false,
                "properties" => [
                    "id" => (int) 188,
                    "name" => "dood dood",
                    "parent_id" => (int) 180,
                    "lft" => (int) 17,
                    "rght" => (int) 18,
                    "children" => []
                ],
                "repository" => "Teams"
            }
        ]
    ],
    "repository" => "Teams"
},

This should work for grandchildren, great-grandchildren, etc., not just for a parent and one child.

Community
  • 1
  • 1
Isaac Askew
  • 1,281
  • 2
  • 17
  • 30
  • Your looking at array questions but your data is an object, have you tried casting to an array and then running the other ideas over it – Dale Sep 26 '14 at 18:18
  • Yeah I'm running 'toArray' on it (CakePHP 3 command), which should have converted it, so I assumed the debug was just an object representation before the conversion. I'll try casting it really quick just to make sure. – Isaac Askew Sep 26 '14 at 18:23

2 Answers2

1

Ultimately, if you want to flatten this down from an unknown tree depth, you need recursion. I've mocked up a slightly more extensive example of your sample object in a file ("test.json"):

{
    "new": false,
    "properties": {
        "children": [
            {
                "new": false,
                "properties": {
                    "children": [],
                    "id": 188,
                    "lft": 17,
                    "name": "dood dood",
                    "parent_id": 180,
                    "rght": 18
                },
                "repository": "Teams"
            },
            {
                "new": false,
                "properties": {
                    "children": [],
                    "id": 182
                },
                "repository": "Teams"
            }
        ],
        "id": 180,
        "lft": 16,
        "name": "Herp de Derp",
        "parent_id": 169,
        "rght": 19
    },
    "repository": "Teams"
}

An example program I created in PHP to enumerate through this is as shown below:

<?php
// $x is the JSON representation of this object (quick for scaffolding purposes)
// $y is the object representation
$x = file_get_contents("test.json");
$y = json_decode($x);

// $memo is our final product, an array that is written to as we traverse the object's children
$memo = [];

// Using recursive closure to walk the object/children and append to $memo
$z = function($n) use (&$z, &$memo) {
    // Build clone $o (sans children) of $n:
    $o = new stdClass;
    $o->new = $n->new;
    $o->repository = $n->repository;
    $o->properties = [];

    $children = [];
    foreach($n->properties as $k => $v) {
        if($k == "children") {
            // Do children afterward, to ensure current object
            // appears in array before children
            $children = $v;
            continue;
        } else {
            $o->properties[$k] = $v;
        }
    }
    array_push($memo, $o);
    array_walk($children, $z);
};
$z($y);
print_r($memo);

$z is my recursive function, which I chose to implement as a closure out of preference. I start off by allocating an empty array ($memo) which is then populated by first prepending the current object, then adding the object's children after the fact. As it traverses the children, the recursive function calls itself for its children, and so on as necessary.

With the above, my output appears as:

Array
(
    [0] => stdClass Object
        (
            [new] => 
            [repository] => Teams
            [properties] => Array
                (
                    [id] => 180
                    [name] => Herp de Derp
                    [parent_id] => 169
                    [lft] => 16
                    [rght] => 19
                )

        )

    [1] => stdClass Object
        (
            [new] => 
            [repository] => Teams
            [properties] => Array
                (
                    [id] => 188
                    [name] => dood dood
                    [parent_id] => 180
                    [lft] => 17
                    [rght] => 18
                )

        )

    [2] => stdClass Object
        (
            [new] => 
            [repository] => Teams
            [properties] => Array
                (
                    [id] => 182
                )

        )

)
Justin Bell
  • 396
  • 1
  • 10
0

What you want is to convert an object to an array:

$arr = (array) $obj;

For json object using json_decode:

$arr = json_decode(json_encode($obj), true);
Adam Sinclair
  • 1,654
  • 12
  • 15