PHP:for循环后数组值的更改

PHP:for循环后数组值的更改,php,arrays,Php,Arrays,我知道标题看起来很奇怪,但这就是我刚刚遇到的情况。 我创建了一个函数,它接受DateTime和integer并返回日期的array,这是我的代码: public static function generateAfterDate(\DateTime $from, $number){ $days = array(); array_push($days, $from); for($i = 1; $i <= $number; $i++){

我知道标题看起来很奇怪,但这就是我刚刚遇到的情况。
我创建了一个函数,它接受
DateTime
integer
并返回日期的
array
,这是我的代码:

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);
第二个给了我这个结果:

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

有人能解释一下吗?

之所以会发生这种情况,是因为包含对象的变量(如
DateTime
对象)实际上并不包含该对象,而是对保存该对象的内存地址的引用

因此,通过将
$from
变量放入
$days
数组,您并不是将DateTime对象及其当前状态的副本放入数组,而是将内存地址引用的副本放入数组。因此,修改
$from
引用指向的日期时间也将修改
$days
数组中每个条目引用的相同日期时间

相反,您需要做的是在将DateTime对象添加到数组中时,将其复制到新的DateTime实例中。幸运的是,PHP有一种简单的方法可以做到这一点:
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
}
array\u push($days,clone$from);
对于($i=1;$i修改(“+1天”);
$days[]=克隆$from;
变量转储($days[$i]->format('d/m/Y');/——第一个变量转储
}

现在,您的
$days
数组仍将包含对内存地址的引用,但它将是一个不同的内存地址,包含每个条目的
DateTime
对象的唯一实例。

发生这种情况是因为变量包含对象(如
DateTime
对象)实际上并不包含该对象,而是对保存该对象的内存地址的引用

因此,通过将
$from
变量放入
$days
数组中,您并不是将DateTime对象及其当前状态的副本放入数组中,而是将内存地址引用的副本放入数组中。因此,修改
$from
引用指向的日期时间也会修改您的
$days
数组中的每个条目都引用了相同的日期时间

相反,您需要做的是在将DateTime对象添加到数组中时将其复制到新的DateTime实例中

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
}
array\u push($days,clone$from);
对于($i=1;$i修改(“+1天”);
$days[]=克隆$from;
变量转储($days[$i]->format('d/m/Y');/——第一个变量转储
}

现在,您的
$days
数组仍将包含对内存地址的引用,但它将是一个不同的内存地址,包含每个条目的
日期时间
对象的唯一实例。

因为我认为您的第一个var_转储是正确的,并且具有预期的结果,第二个仅返回最后一个值,因为ch loop在使用变量$day时创建数组的副本,以便它始终引用正确代码所在的最后一个变量

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

因为我认为您的第一个var_转储是正确的,并且具有预期的结果,所以第二个只返回最后一个值,因为foreach循环在您使用变量$day时创建数组的副本,所以它将始终引用最后一个值。正确的代码是

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