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

PHP 8修改getter返回DateTime意外变更类私有属性问题

问题原因

你存在的认知遗漏是:PHP 中基础类型(字符串、整型、浮点型、布尔型等)的赋值、返回默认是值传递,会生成副本;但对象类型的赋值、返回默认传递的是对象标识符副本,所有持有该标识符的变量都指向同一个对象实例。

你代码中用到的DateTime是典型的可变对象,它的add()方法会直接修改对象自身的属性,不会生成新对象。你通过getStart()拿到的$end和类私有属性$gStart指向完全相同的DateTime实例,对$end调用add()方法自然会修改原属性的值,和引用操作的表现一致。

修复方案

你可以根据业务场景选择以下任意一种方案:

  • 操作前先克隆对象,生成独立副本后再修改
public function getEnd(): ?\DateTimeInterface
{
    $end = $this->getStart();
    if ($end === null) {
        return null;
    }
    $end = clone $end;
    $gInterval = new \DateInterval('P90D');
    $end->add($gInterval);
    return $end;
}
  • 更换为不可变的DateTimeImmutable类型存储时间,ORM 列类型对应修改为datetime_immutable,该类型的add()方法会返回全新的对象实例,不会修改原对象
/**
 * @ORM\Column(type="datetime_immutable")
 */
private ?\DateTimeImmutable $gStart = null;

public function getStart(): ?\DateTimeInterface
{
    return $this->gStart;
}

public function getEnd(): ?\DateTimeInterface
{
    if ($this->getStart() === null) {
        return null;
    }
    $gInterval = new \DateInterval('P90D');
    return $this->getStart()->add($gInterval);
}
  • 直接在 getter 方法中返回克隆对象,从源头避免外部修改类的内部属性
public function getStart(): ?\DateTimeInterface
{
    return $this->gStart ? clone $this->gStart : null;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 21:39:03