0

I know the title looks weird but this is what just happened to me.
I have created a funtion that takes DateTime and integer and return array of dates, and this is my code:

public static function generateAfterDate(\DateTime $from, $number){
        $days = array();
        array_push($days, $from);
        for($i = 1; $i <= $number; $i++){
            $from = $from->modify('+1 day');
            $days[] = $from;
            var_dump($days[$i]->format('d/m/Y'));//---The first var_dump
        }
        foreach ($days as $day){
            var_dump($day->format('d/m/Y'));//--The second var_dump
        }
        die;
        return $days;
    }

generateAfterDate(new \DateTime(), 7);

As you can see I'm using the same array to var_dump data and I get two different results:
The first one gave me this:

string(10) "22/10/2017" string(10) "23/10/2017" string(10) "24/10/2017" string(10) "25/10/2017" string(10) "26/10/2017" string(10) "27/10/2017" string(10) "28/10/2017"

And the second one gave me this result:

string(10) "28/10/2017" string(10) "28/10/2017" string(10) "28/10/2017" string(10) "28/10/2017" string(10) "28/10/2017" string(10) "28/10/2017" string(10) "28/10/2017" string(10) "28/10/2017"

Can someone please explain this ?

2 Answers 2

2

This happens because variables containing objects (like a DateTime object) don't actually contain the object, but a reference to the memory address that holds that object.

So by putting the $from variable into your $days array, you are not putting a copy of your DateTime object with its current state into the array, but you are putting a copy of the memory address reference into the array. Therefore, modifying the DateTime pointed to by the $from reference will also modify the same DateTime referenced by every single entry in your $days array.

What you need to do instead is duplicate the DateTime object and its state to a new DateTime instance when you add it to the array. Fortunately, PHP has a simple way to do just that: clone

array_push($days, clone $from);
for($i = 1; $i <= $number; $i++){
    $from = $from->modify('+1 day');
    $days[] = clone $from;
    var_dump($days[$i]->format('d/m/Y'));//---The first var_dump
}

Now your $days array will still contain references to a memory address, but it will be a different memory address containing a unique instance of a DateTime object for each entry.

Sign up to request clarification or add additional context in comments.

Comments

1

As I think that your first var_dump is the right one with your expected result the second one return only the last value because foreach loop create a copy of the array while you use the variable $day so it will always refer to the last one the right code is

 foreach ($days as $key=>$day){
        var_dump($days[$key]->format('d/m/Y'));//--The  second var_dump
     }

Comments

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.