doctrine orm - tutorial - Campo Doctrine 2 ORM DateTime en el identificador
orm column (2)
En nuestras tablas de refID
datos, las columnas refID
y date
son una clave primaria compuesta, con un campo del identificador asignado como datetime
y 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;
}
}
Si los describimos en la entidad como @ORM / Id, este código devolverá la excepción "no se puede convertir datetime en cadena" ...
$filter = array(
''date'' => $this->stringToDate($loopData[''date'']),
''refID'' => $loopData[''refID'']
));
$oCorpWJ = $this->em->getRepository(''EveDataBundle:corpWalletJournal'')->findOneBy($filter);
// ...
$oCorpWJ->setDate($this->stringToDate($loopData[''date'']));
// ...
Si describimos corpWalletJournal#date
como una columna simple, el código funciona bien. ¿Por qué?
¿Cómo podemos lidiar con eso? Necesitamos tener la date
y el refID
en la clave primaria.
ADICIONAL:
Así que creé nueva clase.
use /DateTime;
class DateTimeEx extends DateTime
{
public function __toString()
{
return $this->format(''Y-m-d h:i:s'');
}
}
Y nuevo tipo para ello.
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;
}
}
¿Cómo puedo usarlos en entidad?
Mi clase de tipo (editada)
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 necesita convertir los campos de identificador en cadenas en UnitOfWork
. Esto es necesario para que el EntityManager
pueda realizar un seguimiento de los cambios en sus objetos.
Como los objetos de tipo DateTime
no implementan el método __toString
forma nativa, convertirlos en cadenas no es tan simple como convertirlos en cadenas.
Por lo tanto, los tipos de date
, datetime
y datetime
predeterminados no son compatibles como parte del identificador .
Para lidiar con esto, debe definir su propio tipo de campo personalizado mydatetime
asignado a su propia clase MyDateTime
que implementa __toString
. De esa manera, el ORM puede manejar identificadores también si contienen objetos.
Aquí hay un ejemplo de cómo puede verse esa clase:
class MyDateTime extends /DateTime
{
public function __toString()
{
return $this->format(''U'');
}
}
Y aquí hay un ejemplo de cómo se vería el tipo DBAL personalizado:
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'';
}
}
Luego lo registra con su configuración de ORM durante el arranque (depende del marco que esté usando). En Symfony, está documentado en la documentación de la doctrina de Symfony .
Después de eso, puedes usarlo en tus entidades:
class corpWalletJournal
{
// ...
/**
* @ORM/Column(name="date", type="mydatetime", nullable=false)
* @ORM/Id
* @ORM/GeneratedValue(strategy="NONE")
*/
private $date;
Ten cuidado con
return new DateTimeEx(''@'' . $dateTime->format(''U''));
La zona horaria no será buena. Deberías hacer :
$val = new DateTimeEx(''@'' . $dateTime->format(''U''));
$val->setTimezone($dateTime->getTimezone());
return $val;