标识符中的Doctrine 2 ORM DateTime字段

use*_*544 17 doctrine-orm

在我们的数据库表中,我们是列refID并且date是复合主键,标识符的一个字段被映射为datetime:

class corpWalletJournal
{
    /**
     * @ORM\Column(name="refID", type="bigint", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="NONE")
     */
    private $refID;

    /**
     * @ORM\Column(name="date", type="datetime", nullable=false)     
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="NONE")
     */
    private $date;

    public function setRefID($refID)
    {
        $this->refID = $refID;
    }

    public function setDate(\DateTime $date)
    {
        $this->date = $date;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我们在实体中将它们描述为@ORM\Id,则此代码将返回异常"无法将datetime转换为字符串"...

$filter = array(
    'date' => $this->stringToDate($loopData['date']), 
    'refID' => $loopData['refID']
));

$oCorpWJ = $this->em->getRepository('EveDataBundle:corpWalletJournal')->findOneBy($filter);
// ...
$oCorpWJ->setDate($this->stringToDate($loopData['date']));
// ...
Run Code Online (Sandbox Code Playgroud)

如果我们描述corpWalletJournal#date为一个简单的列,代码工作正常.为什么?

我们该如何处理它?我们需要在主键中同时使用daterefID.

添加:

所以我创造了新课程

use \DateTime;

class DateTimeEx extends DateTime
{

public function __toString()
{
    return $this->format('Y-m-d h:i:s');
}

}
Run Code Online (Sandbox Code Playgroud)

并为它新的类型

use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Eve\DataBundle\Entity\Type\DateTimeEx;

class DateTimeEx extends Type
{
    const DateTimeEx = 'datetime_ex';

    public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
    {
        return 'my_datetime_ex';
    }

    public function convertToPHPValue($value, AbstractPlatform $platform)
    {
        return new DateTimeEx($value);
    }

    public function convertToDatabaseValue($value, AbstractPlatform $platform)
    {
        return $value->format('Y-m-d h:i:s');
    }

    public function getName()
    {
        return self::DateTimeEx;
    }

    public function canRequireSQLConversion()
    {
        return true;
    }

}
Run Code Online (Sandbox Code Playgroud)

我如何在实体中使用它们?

我的(编辑)类型类

    use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Platforms\AbstractPlatform;

class DateTimeEx extends Type
{
    const DateTimeEx = 'datetime_ex';

    public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
    {
        return 'my_datetime_ex';
    }

    public function convertToPHPValue($value, AbstractPlatform $platform)
    {
        return $value;
    }

    public function convertToDatabaseValue($value, AbstractPlatform $platform)
    {
        return $value;
    }

    public function getName()
    {
        return self::DateTimeEx;
    }

}
Run Code Online (Sandbox Code Playgroud)

Ocr*_*ius 36

Doctrine 2 ORM需要将标识符字段转换为字符串UnitOfWork.这需要EntityManager能够跟踪对象的更改.

由于类型的对象DateTime本身并不实现方法__toString,因此将它们转换为字符串并不像将它们转换为字符串那么简单.

因此,默认date,datetimetime类型不被支持作为标识符的一部分.

要处理它,您应该定义自己的自定义字段类型, mydatetime映射到您自己的MyDateTime类实现__toString.这样,如果ORM包含对象,ORM也可以处理标识符.

以下是该类的外观示例:

class MyDateTime extends \DateTime 
{
    public function __toString()
    {
        return $this->format('U');
    }
}
Run Code Online (Sandbox Code Playgroud)

以下是自定义DBAL类型的示例:

use Doctrine\DBAL\Types\DateTimeType;
use Doctrine\DBAL\Platforms\AbstractPlatform;

class MyDateTimeType extends DateTimeType
{
    public function convertToPHPValue($value, AbstractPlatform $platform)
    {
        $dateTime = parent::convertToPHPValue($value, $platform);

        if ( ! $dateTime) {
            return $dateTime;
        }

        return new MyDateTime('@' . $dateTime->format('U'));
    }

    public function getName()
    {
        return 'mydatetime';
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在引导期间使用ORM配置注册它(取决于您使用的框架).在symfony中,它记录在symfony doctrine文档中.

之后,您可以在您的实体中使用它:

class corpWalletJournal
{
    // ...

    /**
     * @ORM\Column(name="date", type="mydatetime", nullable=false)     
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="NONE")
     */
    private $date;
Run Code Online (Sandbox Code Playgroud)

  • 我注意到了一些副作用:1) **doctrine:schema:update** 工具不断尝试更新自定义日期字段,因为 Doctrine 的“Comparator”在数据库中看到“DateTime”,在数据库中看到“MyDateTime”。本地代码。2) 您必须将用于查询此字段的任何值转换为与自定义类型相同的类型,例如 `$queryBuilder->setParameter('date', new MyDateTime('@'.$dateTime->format('U ')))`。 (2认同)