Многие люди ответили, но никто не упомянул об этом до сих пор ...
Атрибуты используются сильно с отражением.
очень полезно , отмечая ваши пользовательские атрибуты как классы sealed
, чтобы улучшить их производительность во время выполнения.
Это также хорошая идея рассмотреть, где было бы целесообразно использовать такой атрибут, и приписать свой атрибут (!), чтобы указать это через AttributeUsage
. Список доступных атрибутов может удивить вас:
Также здорово, что атрибут AttributeUsage является частью подписи атрибута AttributeUsage. Whoa для круговых зависимостей!
[AttributeUsageAttribute(AttributeTargets.Class, Inherited = true)]
public sealed class AttributeUsageAttribute : Attribute
экземпляры DateTime
, возвращенные ExampleBundle\Entity\User#getServiceExpiresAt()
, - это те же объекты, которые хранятся в самой сущности, которая прерывает инкапсуляцию .
Применяется UnitOfWork в ORM доктрины строгое сравнение для наборов изменений , что в основном означает, что в случае свойств объектов, содержащих объекты, если экземпляр объекта не изменился, ORM не обнаруживает изменения.
При строгом сравнении , верно следующее:
$dateTime1 = new \DateTime('@0');
$dateTime2 = new \DateTime('@0');
$dateTime3 = $dateTime1;
var_dump($dateTime1 !== $dateTime2); // true
var_dump($dateTime1 === $dateTime3); // true
$dateTime1->modify('+1 day');
var_dump($dateTime1 === $dateTime3); // true
Это очень распространенная ошибка среди новичков в программировании ООП, и ее можно быстро решить, установив ваши геттеры и сеттеры, чтобы исходный экземпляр никогда не делился вне вашего объект, как в следующем примере:
public function getServiceExpiresAt()
{
return clone $this->service_expires_at;
}
public function setServiceExpiresAt(\DateTime $service_expires_at)
{
$this->service_expires_at = clone $service_expires_at;
}
Это также устранит вашу проблему с помощью Doctrine ORM.
Также обратите внимание, что это устраняет возможные утечки в вашей логике. Например, следующий код ошибочен и трудно отлаживается (при применении ваших сломанных геттеров / сеттеров):
$bankTransaction1 = $someService->getTransaction(1);
$bankTransaction2 = $someService->getTransaction(2);
// leak! Now both objects reference the same DateTime instance!
$bankTransaction2->setDateTime($bankTransaction1->getDateTime());
// bug! now both your objects were modified!
$bankTransaction1->getDateTime()->modify('+1 day');
Итак, независимо от части ORM в вопросе, пожалуйста, не прерывайте инкапсуляцию.
У меня точно такая же проблема, когда я пытаюсь вставить объект с прошлой датой (я пытаюсь перенести старую базу данных в новую схему с ее данными тоже).
Я попытался клонировать объект как в сеттер, так и в getter, и это бесполезно. Doctrine 2 сохраняет текущую дату. Проверяемая схема, поле - это дата не время штампа, а по умолчанию - значение null.
Как это может быть?
EDIT:
, пожалуйста, извините, внимание, мой коллега Dev добавил событие prePersist:
/**
* @ORM\PrePersist
*/
function onPrePersist() {
$this->created_at = new \DateTime('now');
}
С помощью класса DateTimeImmutable рассмотрите свойства даты и времени. Тем самым обратите внимание, что DateTimeImmutable не является экземпляром DateTime .
INSERT ... SELECT ...
) – Ocramius 3 October 2017 в 17:33