22

在我们的数据库表中,我们列refIDdate是一个复合主键,标识符的一个字段被映射为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;
    }
}

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

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

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

如果我们将其描述corpWalletJournal#date为一个简单的列,则代码可以正常工作。为什么?

我们该如何应对?我们需要同时拥有daterefID在主键中。

添加:

所以我创建了新课程

use \DateTime;

class DateTimeEx extends DateTime
{

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

}

和它的新类型

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;
    }

}

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

我的(编辑的)类型类

    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;
    }

}
4

2 回答 2

44

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

由于 type 对象DateTime本身并不实现 method __toString,因此将它们转换为字符串并不像将它们转换为字符串那么简单。

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

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

这是该类的外观示例:

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

下面是自定义 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 requiresSQLCommentHint(AbstractPlatform $platform)
    {
        return true;
    }

    public function getName()
    {
        return 'mydatetime';
    }
}

然后在引导期间将其注册到您的 ORM 配置中(取决于您使用的框架)。在 symfony 中,它记录在symfony 学说文档中。

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

class corpWalletJournal
{
    // ...

    /**
     * @ORM\Column(name="date", type="mydatetime", nullable=false)     
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="NONE")
     */
    private $date;
于 2013-02-26T09:33:17.390 回答
3

小心

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

时区不会很好。你应该做 :

$val = new DateTimeEx('@' . $dateTime->format('U'));
$val->setTimezone($dateTime->getTimezone());

return $val;
于 2016-01-26T13:25:56.730 回答