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('THINT POINT IS NREER REACHED')" никогда не достигается ". (Обратите внимание на @ORM\PreUpdate) Это означает, что lifecycleCallbacks не вызываются для унаследованных объектов. Это ошибка, или есть причина для этого?

7 ответов

Решение

Ваш абстрактный базовый класс должен быть аннотирован как сопоставленные суперклассы и включать аннотацию HasLifecycleCallbacks.

Дополнительная информация: Карта наследования в документации доктрины.

/**
 * @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.
}

Вы должны аннотировать базовый класс @ORM\HasLifecycleCallbacksи функция с @ORM\preUpdate

У вас есть опечатка (PreUpdate должно быть preUpdate), также preUpdate не вызывается при создании (только при обновлении). Поэтому, если вы хотите, чтобы он также был запущен при создании, вы должны добавить @ORM\prePersist,

Хотя принятый ответ является правильным для общего случая, в данном конкретном случае (отметка времени) вы на самом деле хотите использовать расширение доктрины Timestampable, как описано, например, здесь. Проблема обратного вызова жизненного цикла при расширении объекта пользователя FOSUserBundle

Важно, чтобы MappedSuperclass с HasLifecycleCallbacks находился в том же пространстве имен или каталоге, что и их дочерние сущности.

У меня были проблемы с обратными вызовами жизненного цикла, когда MappedSuperclass находился в одном каталоге (Model), а сущности были в другом (Entity). Помещение MappedSuperclass в тот же каталог, в котором находятся Entities (Entity), решило проблему.

Возможно, вы могли бы сообщить об этой проблеме как справочную информацию о том, как настроить аннотации? Тестовый сценарий, кажется, действителен и соответствует вашему варианту использования.

Может быть, я ошибаюсь, но я не думаю, что preUpdate не срабатывает, когда вы сохраняете сущность. У вас должен быть @prePersist.

http://www.doctrine-project.org/docs/orm/2.0/en/reference/events.html

Но все же тогда я не уверен, что это сработает, но вы можете попробовать это. В противном случае обходным путем может быть перезапись функции setUpdatedAt и просто вызов его родительской функции, но это немного уродливо.

Надеюсь, @prePersist поможет вам.

Я думаю, что вы должны аннотировать базовый класс с помощью @ORM\HasLifecycleCallbacks

документы

Другие вопросы по тегам