【问题标题】:Doctrine is storing the wrong value in DB from a DateTime objectDoctrine 在 DB 中从 DateTime 对象中存储了错误的值
【发布时间】:2017-03-20 14:41:13
【问题描述】:

我有以下实体:

use Doctrine\ORM\Mapping as ORM;
use Gedmo\Timestampable\Traits\TimestampableEntity;

class Quote
{
    use SourceTrait;
    use TimestampableEntity;

    private $quoteId;

    private $startDate;

    private $endDate;


    public function getStartDate(): ?\DateTime
    {
        return $this->startDate;
    }


    public function setStartDate(\DateTime $startDate)
    {
        $this->startDate = $startDate;
    }

    public function getEndDate(): ?\DateTime
    {
        return $this->endDate;
    }


    public function setEndDate(\DateTime $endDate)
    {
        $this->endDate = $endDate;
    }

}

我在QuoteRepository 类中有这个方法:

public function createQuoteHeader(Agreement $agreement): int
{
    $em      = $this->getEntityManager();
    $QuoteID = $this->getNewQuoteId();
    $year    = $agreement->getEndDate()->diff($agreement->getStartDate(), true)->y > 0
        ? $agreement->getEndDate()->diff($agreement->getStartDate(), true)->y
        : 0;

    dump($year);
    dump(gettype($year));
    dump($agreement->getEndDate());

    $entity = new Quote();
    ...
    $entity->setStartDate($agreement->getEndDate()->modify('+1 day'));
    dump($agreement->getStartDate());
    $entity->setEndDate($agreement->getEndDate()->modify("+1 day +{$year} year"));
    dump($agreement->getEndDate());
    ...

    $em->persist($entity);
    $em->flush();

    return $entity->getQuoteId();
}

上面dump()的输出如下(与代码中的顺序相同):

0
"integer"
DateTime {#3005
  +"date": "2017-03-21 00:00:00.000000"
  +"timezone_type": 3
  +"timezone": "UTC"
}
DateTime {#3004
  +"date": "2016-03-22 00:00:00.000000"
  +"timezone_type": 3
  +"timezone": "UTC"
}
DateTime {#3005
  +"date": "2017-03-23 00:00:00.000000"
  +"timezone_type": 3
  +"timezone": "UTC"
}

在 DB 中插入了错误的值:

也许我遗漏了一些东西,但不应该是 StartDate 等于 2016-03-22 00:00:00??

【问题讨论】:

    标签: php symfony doctrine-orm doctrine symfony-3.2


    【解决方案1】:

    让我们逐行浏览您的代码。

    $entity->setStartDate($agreement->getEndDate()->modify('+1 day'));
    

    modify() 改变被调用的DateTime 对象。 此行将 +1 天添加到 $agreement->getEndDate() 并且 same 日期时间传递给 $entity->setStartDate()。所以$agreement->getEndDate()$entity->getStartDate() 都将返回 2017-03-22!

    dump($agreement->getStartDate());
    

    您转储了错误的日期,因此是 2016-03-22,从而掩盖了错误。应该是dump($entity->getStartDate());,你会注意到的。

    $entity->setEndDate($agreement->getEndDate()->modify("+1 day +{$year} year"));
    

    由于 $agreement->getEndDate() 现在等于 2017-03-22,+1 天 +0 年将导致 $entity->getEndDate() 等于 2017-03-23。

    我建议使用DateTimeImmutable 来避免所有这些不必要的对象引用问题。

    【讨论】:

      【解决方案2】:

      您尝试保留的对象似乎有问题。当您进行转储()时,您将获得正确的结果,但日期时间对象稍后会被修改,因此当您持久保存该对象时,所有值都会获得您的最后一个日期时间结果。 我建议您在日期时间对象中进行“克隆”,并单独设置值,如下所示:

      $oDatetime1  = clone($agreement->getEndDate());
      $oDatetime2  = clone($agreement->getEndDate());
      
      $entity->setStartDate($oDatetime1->modify('+1 day'));
      $entity->setEndDate($oDatetime2->modify("+1 day +{$year} year"));
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-07-14
        • 2017-07-25
        • 2016-04-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多