You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP嵌套for循环中DateTime值被覆盖致输出异常求助

嵌套循环中DateTime对象的引用问题分析与修复

问题根源

你猜的没错,问题出在PHP的DateTime是引用类型,赋值时传递的是对象引用而非副本:

  • 外层循环中,$i = $begin_from让$i指向原$begin_from对象,每次modify会修改原对象,但外层循环还能正常迭代,因为每次+1月直到超过$end_from。
  • 内层循环中,$k = $begin_to直接让$k指向原$begin_to对象,第一次内层循环执行时,每次modify都会直接修改$begin_to本身。当第一次内层循环跑完,$begin_to已经被修改为2024-01-31(超出$end_to的范围),后续外层循环迭代时,内层循环的初始条件$k <= $end_to直接不成立,所以只会输出第一次外层循环的结果。

修复方案

需要在每次进入内层循环时,创建$begin_to的独立副本,使用clone关键字即可(DateTime对象支持克隆):

<?php

$begin_from = new DateTime("2023-01-01");
$end_from   = new DateTime("2023-12-31");

$begin_to = new DateTime("2023-01-31");
$end_to   = new DateTime("2023-12-31");

for($i = $begin_from; $i <= $end_from; $i->modify('+1 month')){
    // 每次内层循环克隆原对象,避免修改$begin_to的初始值
    $current_to = clone $begin_to;
    for($k = $current_to; $k <= $end_to; $k->modify('first day of')->modify('+1 month')->modify('last day of')){
        echo $i->format("Y-m-d"),'..',$k->format("Y-m-d");
        echo "\n";
    }
}

更简洁的实现方式

如果你的需求是输出每个月的1号到当月月末,完全可以直接基于$i的月份计算月末,不需要单独维护$begin_to,代码更简洁:

<?php

$begin_from = new DateTime("2023-01-01");
$end_from   = new DateTime("2023-12-31");

// 克隆初始对象,避免修改原$begin_from
for($i = clone $begin_from; $i <= $end_from; $i->modify('+1 month')){
    $month_end = clone $i;
    $month_end->modify('last day of this month');
    echo $i->format("Y-m-d"),'..',$month_end->format("Y-m-d");
    echo "\n";
}

内容的提问来源于stack exchange,提问作者samz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 14:35:27