Reputation: 3564
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 ?
Upvotes: 0
Views: 73
Reputation: 3040
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
}
Upvotes: 1
Reputation: 11318
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.
Upvotes: 2