Doctrine 2 LifecycleCallbacks с абстрактным базовым классом не называются
У меня такая ситуация:
Абстрактный класс:
abstract class AbstractBase
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
* @var integer
*/
protected $id;
/**
* @ORM\Column(type="datetime", name="updated_at")
* @var \DateTime $updatedAt
*/
protected $updatedAt;
/**
* @ORM\PreUpdate
*/
public function setUpdatedAt()
{
die('THIS POINT IS NEVER REACHED');
$this->updatedAt = new \DateTime();
}
}
Класс бетона:
/**
* @ORM\Entity(repositoryClass="Entity\Repository\UserRepository")
* @ORM\Table(name="users")
* @ORM\HasLifecycleCallbacks
*/
class User extends AbstractBase
{
// some fields, relations and setters/getters defined here, these all work as expected.
}
Затем я вызываю его в своем контроллере следующим образом:
$user = $this->em->find('Entity\User', 1);
// i call some setters here like $user->setName('asd');
$this->em->flush();
die('end');
Все работает так, как ожидалось, поэтому поле id из абстрактного класса создается для объекта User, я могу получить к нему доступ и т.д.
Проблема в том, что линия "die (" ЭТОТ ТОЧКА НИКОГДА НЕ ДОСТИГАЕТСЯ ")" никогда не достигается. (Обратите внимание на @ORM\PreUpdate) Это означает, что lifecycleCallbacks не вызываются
наследуемых объектов. Это ошибка, или есть причина для этого?
Ответы
Ответ 1
Ваш абстрактный базовый класс должен быть объявлен как сопоставленные суперклассы и включать HasLifecycleCallbacks -Annotation.
Дополнительная информация: Наследование в документации Doctrine.
/**
* @ORM\MappedSuperclass
* @ORM\HasLifecycleCallbacks
*/
abstract class AbstractBase
{
[...]
/**
* @ORM\PreUpdate
*/
public function setUpdatedAt()
{
$this->updatedAt = new \DateTime();
}
}
/**
* @ORM\Entity(repositoryClass="Entity\Repository\UserRepository")
* @ORM\Table(name="users")
*/
class User extends AbstractBase
{
// some fields, relations and setters/getters defined here, these all work as expected.
}
Ответ 2
Вы должны аннотировать базовый класс с помощью @ORM\HasLifecycleCallbacks
, а функция с @ORM\preUpdate
У вас есть опечатка (PreUpdate должен быть preUpdate), также preUpdate не вызывается при создании (только при обновлении). Поэтому, если вы хотите, чтобы он также срабатывал при создании, вы должны добавить @ORM\prePersist
.
Ответ 3
В то время как принятый ответ правильный для общего случая, в данном конкретном случае (временная метка) вы действительно хотите использовать расширение доктрины Timestampable, как описано здесь, например здесь Проблема обратного вызова жизненного цикла при расширении Пользовательский объект FOSUserBundle
Ответ 4
Возможно, я ошибаюсь, но я не думаю, что preUpdate не запускается, когда вы сохраняете сущность. У вас должен быть @prePersist.
http://www.doctrine-project.org/docs/orm/2.0/en/reference/events.html
Но все же я не уверен, что это сработает, но вы можете попробовать это. Кроме того, обходным решением было бы перезаписать функцию setUpdatedAt и просто вызвать его родительский, но это немного уродливо.
Надеемся, что @prePersist поможет вам.
Ответ 5
Возможно, вы могли бы это отчет о выпуске в качестве ссылки, как настроить аннотации? Вероятно, тестовый файл действителен и соответствует вашему варианту использования.
Ответ 6
Важно, что MappedSuperclass с HasLifecycleCallbacks находится в том же пространстве имен или в каталоге, что и их дочерние сущности.
У меня были проблемы с обратными вызовами жизненного цикла, когда MappedSuperclass находился в одном каталоге (Модель), в то время как Сущности находились в другом (Entity). Помещение MappedSuperclass в тот же каталог, что и Entities (Entity), решило проблему.
Ответ 7
Я думаю, что вы должны аннотировать базовый класс с помощью @ORM\HasLifecycleCallbacks
docs