【问题标题】:Symfony2/Doctrine2 - Issue when getting datetime from databaseSymfony2/Doctrine2 - 从数据库获取日期时间时的问题
【发布时间】:2013-12-20 17:16:13
【问题描述】:

当我在处理我的 Symfony2 项目时,一个奇怪的错误(再次)突然出现了。

我创建了一个实体Check,其中包含一个dateCreated 属性和一些其他属性,因此我可以将Check 链接到扩展ProductBase 的不同实体。以下是CheckAProduct 的示例:

/**
 * Check
 *
 * @ORM\Table(name="check")
 * @ORM\Entity
 */
class Check
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="date_created", type="datetime")
     */
    private $dateCreated;
    [...]


/**
 * @ORM\ManyToOne(targetEntity="Acme\BlogBundle\Entity\AProduct", inversedBy="checks")
 * @ORM\JoinColumn(name="aproduct_id", referencedColumnName="id", onDelete="CASCADE")
 */
protected $aproduct;
    [...]
}


/**
 * AProduct
 *
 * @ORM\Table(name="aproduct")
 * @ORM\Entity
 */
class AProduct extends ProductBase
{
    [...]


    /**
     * @ORM\OneToMany(targetEntity="Acme\BlogBundle\Entity\Check", mappedBy="product")
     * @ORM\OrderBy({"dateCreated" = "DESC"})
     */
    protected $checks;
    [...]
}

所以我的问题是,当我试图在我的一个控制器中显示 dateCreated 属性时,请参见下面的代码,Symfony2(或 Doctrine2)正在将一个月的日期添加到存储在数据库中的日期,而我没有不知道为什么会这样:

[...]
$aproduct = $aproducts[0];
$checks = $aproduct->getChecks();
$lastCheck = $checks->toArray()[0]; //I know it's not 'safe' but it's shorter to expose my problem
var_dump($lastCheck->getDateCreated());

结果:

object(DateTime)[854]
  public 'date' => string '2014-01-20 16:21:41' (length=19)
  public 'timezone_type' => int 3
  public 'timezone' => string 'UTC' (length=3)

存储在数据库中的值:

2013-12-20 16:21:41

我最不明白的是,在另一个控制器中,使用完全相同的方法但在不同的产品上(例如BProduct),我得到了正确的日期...... 有没有人已经遇到过这个问题或知道如何解决这个问题?

再次感谢您。如果您需要更多信息,请询问,我会尽我所能提供帮助。

编辑:存储在aproducts 中的其他aproduct 正在显示正确的日期...

【问题讨论】:

  • 您是否使用此处建议的自定义日期时间类型? docs.doctrine-project.org/en/2.0.x/cookbook/…
  • @YRM 为什么时区会影响 DateTime 整个月?
  • 我会打印调试 Doctrine\DBAL\Types\DateTimeType::convertToPHPValue() 中发生的情况,问题可能出在您自己的代码中。
  • @sjagr 不会,我只是问他是否使用自定义日期时间,因为那时我们需要看到它..
  • @YRM 不,我没有在这里使用自定义日期时间。但我想知道和sjagr一样的事情。你的演讲很有趣。

标签: php database datetime symfony doctrine-orm


【解决方案1】:

我看到你正在使用:

@ORM\OrderBy({"dateCreated" = "DESC"})

可能有点傻,但请检查返回的 Check 实例的 id。

【讨论】:

  • 这并不傻。但是Check 实例的 id 是好的。
  • 好的。 ProductBase.php 中有一些重要的代码吗?你把$this->checks = new ArrayCollection() 放在__construct 中了吗?
  • 此行存在。 ProductBase 中没有重要的代码,只有基本的 getter 和 setter……没有其他代码与这些实体中的检查交互……明天我将继续到处寻找,也许会找到这个问题的来源。谢谢大家帮助我
【解决方案2】:

好吧,我终于找到了我的问题,我在这里的帖子真的很愚蠢,与 Symfony 或 Doctrine 完全无关,对此感到抱歉。 在显示它们之前,我在我的 aproduct 检查的最后一个实例上执行了一些“测试”,这些“测试”正在影响 dateCreated 值。 这是我正在做的事情:

public static function updateAProductStatus(AProduct $product){
    if(($check = $product->getChecks()->first()) instanceof Check){
        $date = $check->getDateCreated();
        $expiracyDate = $date->add(new \DateInterval('P1M')); //this line is the problem
        $status = self::getStatus($expiracyDate); //this is only returning 'expired', 'expiring' or 'good' based on the difference between today's date and dateCreated + 1 month
    } else {
        $status = 'expired';
    }
    return $status;
}

因此,正如代码中所写,$date->add(new \DateInterval('P1M')); 正在更改 ChecksdateCreated 属性的存储值。我不明白为什么它会影响它,因为我没有直接在 Check 实例上工作。

解决此问题的快速方法是在添加 DateInterval 之前显式克隆 DateTime 实例:

$date = clone $date;

但我会在我的CheckAProduct 实体中添加一个新字段来存储到期日期,而不是在每次更新时计算它。

更新:

我读到 PHP 将对象和数组作为引用而不是作为值传递。这就是我在这里遇到问题的原因。我不知道 PHP 的行为是这样的。那我以后会更小心的!

【讨论】:

    猜你喜欢
    • 2013-04-13
    • 2017-05-17
    • 1970-01-01
    • 1970-01-01
    • 2015-11-19
    • 2016-05-12
    • 2013-04-01
    • 1970-01-01
    • 2019-08-23
    相关资源
    最近更新 更多