【问题标题】:Symfony/Doctrine: DateTime as primary keySymfony/Doctrine:日期时间作为主键
【发布时间】:2014-11-27 08:18:00
【问题描述】:

我正在尝试使用日期作为主键来创建实体。问题是 Symfony 无法将我使用的 DateTime 转换为字符串以将其引入 IdentityMap。在实体持久化过程中出现以下错误:

Catchable Fatal Error: Object of class DateTime could not be converted to string in..

我在实体中使用此代码:

/**
 * @ORM\Id
 * @ORM\Column(type="datetime")
 */
protected $date;

实体仓库中出现错误:

$em = $this->getEntityManager();
$currentData = new CurrentData();
...
$currentData->setDate(new \DateTime($dateStr));
...
$em->persist($currentData);
$em->flush();

我该如何解决这个问题?谢谢。

【问题讨论】:

标签: datetime symfony doctrine primary-key


【解决方案1】:

对此的可靠解决方案是实现您自己的 DBAL 类型,使用实现了 __toString() 的 DateTime 后代:

<?php
class DateKey extends \DateTime{
    function __toString() {
        return $this->format('c');
    }

    static function fromDateTime(\DateTime $dateTime) {
        return new static($dateTime->format('c'));
    }
}

class DateKeyType extends \Doctrine\DBAL\Types\DateType{
    public function convertToPHPValue($value, \Doctrine\DBAL\Platforms\AbstractPlatform $platform) {
        $value = parent::convertToPHPValue($value, $platform);
        if ($value !== NULL) {
            $value = DateKey::fromDateTime($value);
        }
        return $value;
    }
    public function getName()
    {
        return 'DateKey';
    }
}

\Doctrine\DBAL\Types\Type::addType('datekey', 'DateKeyType');
//edit: do not forget this after creating entity manager.
//otherwise, you will get into problems with doctrine database diff / migrations.
$platform = $entityManager->getConnection()->getDatabasePlatform();
$platform->registerDoctrineTypeMapping('datekey', 'datekey');
$platform->markDoctrineTypeCommented(\Doctrine\DBAL\Types\Type::getType('datekey'));

【讨论】:

    【解决方案2】:

    我在这里遇到了同样的问题。我通过使用这个来解决它:

    /**
     * @var string
     *
     * @ORM\Id
     * @ORM\Column(type="string")
     */
    private $date;
    
    /**
     * @return \DateTime
     */
    public function getDate()
    {
        return \DateTime::createFromFormat('Y-m-d|', $this->date);
    }
    
    /**
     * @param \DateTime $date
     */
    public function __construct(\DateTime $date)
    {
        $this->date = $date->format('Y-m-d');
    }
    

    如果您想使用日期时间,您应该使用不同的格式,例如 \DateTime::ISO8601。使用时区保存内容时要小心。

    【讨论】:

      【解决方案3】:

      您可能应该只使用正常的序列。

      但是,如果您必须使用日历信息作为键,您可能希望将其存储为“字符串”类型,然后使用 php 的 DateTime 格式:

       $currentData->setDate(new \DateTime($dateStr)->format('yyyy/mm/dd');
      

      如果您尝试使用日期时间对象作为键,您可能会陷入困境。

      【讨论】:

      • 你不应该假设一个正常的序列对他的目的更有用或更快。像这样的建议,在不了解他的用例的情况下,可能会导致糟糕的数据库设计。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-06
      • 1970-01-01
      相关资源
      最近更新 更多