In our DB tables, we columns refID
and date
are a composite primary key, with one field of the identifier being mapped as a 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; } }
If we describe them in entity as @ORM\Id this code will return exception "cannot convert datetime to string"...
$filter = array( 'date' => $this->stringToDate($loopData['date']), 'refID' => $loopData['refID'] )); $oCorpWJ = $this->em->getRepository('EveDataBundle:corpWalletJournal')->findOneBy($filter); // ... $oCorpWJ->setDate($this->stringToDate($loopData['date'])); // ...
If we describe corpWalletJournal#date
as a simple column, code works fine. Why?
How can we deal with it? We need to have both date
and refID
in the primary key.
ADDED:
So i created new class
use \DateTime; class DateTimeEx extends DateTime { public function __toString() { return $this->format('Y-m-d h:i:s'); } }
And new type for it
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; } }
How can i use them in entity?
My (edited) Type Class
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; } }
Doctrine 2 ORM needs to convert identifier fields to strings in the UnitOfWork
. This is required to have the EntityManager
being able to track changes to your objects.
Since objects of type DateTime
don't natively implement method __toString
, converting them to strings is not as simple as casting them to strings.
Therefore, the default date
, datetime
and time
types are not supported as part of the identifier.
To deal with it, you should define your own custom field type mydatetime
mapped to your own MyDateTime
class which implements __toString
. That way, the ORM can handle identifiers also if they contain objects.
Here's an example of how that class may look like:
class MyDateTime extends \DateTime { public function __toString() { return $this->format('U'); } }
And here's an example of how the custom DBAL type would look like:
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; } $val = new MyDateTime('@' . $dateTime->format('U')); $val->setTimezone($dateTime->getTimezone()); return $val; } public function requiresSQLCommentHint(AbstractPlatform $platform) { return true; } public function getName() { return 'mydatetime'; } }
Then you register it with your ORM configuration during bootstrap (depends on the framework you are using). In symfony, it is documented on the symfony doctrine documentation.
After that, you can use it in your entities:
class corpWalletJournal { // ... /** * @ORM\Column(name="date", type="mydatetime", nullable=false) * @ORM\Id * @ORM\GeneratedValue(strategy="NONE") */ private $date;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With