1

After far too many hours troubleshooting what I expected to be a straight forward task, I believe I'm either missing an obvious flaw or have constructed an erroneous mental model of how it should work.

My actual data is much more complex, but I've simplified it down to this example.

Let's say I have an array $my_array of objects:

$object1 = new stdClass();
    $object1->valueA = 'abc';
    $object1->valueB = 'def';
    $object1->valueC = '20160410';
$object2 = new stdClass();
    $object2->valueA = '123';
    $object2->valueB = '456';
    $object2->valueC = '20160408';
$object3 = new stdClass();
    $object3->valueA = 'foo';
    $object3->valueB = 'bar';
    $object3->valueC = '20160412';

$my_array = array(
    'X' => $object1,
    'Y' => $object2,
    'Z' => $object3
);

I want to go through each object, use one of its values to calculate a new property, then assign the object to a new array, using the new calculate value to group them.

I did it this way:

$new_array= array();
foreach($my_array as $key=>$obj){
    for($i=0;$i<=2;$i++){  //the real use case uses a slightly different loop, this is simpler/shorter for an example 
        $date = $obj->valueC + $i;  //use valueC and the loop to calculate a new value
        $obj->date = $date;  //add my new value to the object
        $new_array[$date][$key] = $obj;  //construct new array of arrays of objects. bits on bits on bytes.
    }
}

If I log the resulting array to Console, it looks like this:

[04-Apr-2016 22:09:28 UTC] Array
(
    [20160410] => Array
        (
            [X] => stdClass Object
                (
                    [valueA] => abc
                    [valueB] => def
                    [valueC] => 20160410
                    [date] => 20160412
                )

            [Y] => stdClass Object
                (
                    [valueA] => 123
                    [valueB] => 456
                    [valueC] => 20160408
                    [date] => 20160410
                )

        )

    [20160411] => Array
        (
            [X] => stdClass Object
                (
                    [valueA] => abc
                    [valueB] => def
                    [valueC] => 20160410
                    [date] => 20160412
                )

        )

    [20160412] => Array
        (
            [X] => stdClass Object
                (
                    [valueA] => abc
                    [valueB] => def
                    [valueC] => 20160410
                    [date] => 20160412
                )

            [Z] => stdClass Object
                (
                    [valueA] => foo
                    [valueB] => bar
                    [valueC] => 20160412
                    [date] => 20160414
                )

        )

    [20160408] => Array
        (
            [Y] => stdClass Object
                (
                    [valueA] => 123
                    [valueB] => 456
                    [valueC] => 20160408
                    [date] => 20160410
                )

        )

    [20160409] => Array
        (
            [Y] => stdClass Object
                (
                    [valueA] => 123
                    [valueB] => 456
                    [valueC] => 20160408
                    [date] => 20160410
                )

        )

    [20160413] => Array
        (
            [Z] => stdClass Object
                (
                    [valueA] => foo
                    [valueB] => bar
                    [valueC] => 20160412
                    [date] => 20160414
                )

        )

    [20160414] => Array
        (
            [Z] => stdClass Object
                (
                    [valueA] => foo
                    [valueB] => bar
                    [valueC] => 20160412
                    [date] => 20160414
                )

        )

)

Now, I would expect $new_array['20160410']['X']->date to be 20160410. After all, within 2 lines, I said, "use this value as the top-level array key and also as the value in the object". But no matter what I do, all instances of ['X'] will have the same date value. Same for ['Y'] and ['Z'].

My aim is to be able to store the newly calculated date value within the object while also using that value as a grouping key.

2
  • You started good with noticing, that all values are the same for each object of your array. Next step would have been to check the manuals for everything you use in your code. Commented Apr 4, 2016 at 22:31
  • This would be trivial if the data were in a relational database. Commented Apr 4, 2016 at 22:44

1 Answer 1

3

Objects get assigned by reference by default, as you can read it it in the manual:

One of the key-points of PHP 5 OOP that is often mentioned is that "objects are passed by references by default".

So you can imagine your assignment in the for loop:

$new_array[$date][$key] = $obj;

like this:

$new_array[$date][$key] = &$obj;
                          ↑

This means you will update all objects every iteration of the for loop. To solve this just clone the object, e.g.

$new_array[$date][$key] = clone $obj;
Sign up to request clarification or add additional context in comments.

2 Comments

Wow - you've just cleared up a long-standing misconception I've had about objects and I can immediately see how they might be useful in lots of ways I hadn't considered before. I only wish I'd posted this 2 days ago before I'd sunk so many hours into debugging! Next time, maybe I'll try the ole RTFM approach. Thanks!
@AndrewCafourek It's not a bad thing if you debug for a long time. Maybe next time just start reading the manual about everything you use in the code ;)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.