Doctrine 2 LifecycleCallbacks with abstract base c

2019-01-14 12:33发布

I have this situation:

Abstract Class:

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();
    }
}

Concrete Class:

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

Then i call it in my controller like this:

$user = $this->em->find('Entity\User', 1);
// i call some setters here like $user->setName('asd');
$this->em->flush();
die('end');

Everything works as expected, so the id field from the abstract class gets created for the User entity, i can access it etc. The problem is, that the line "die('THIS POINT IS NEVER REACHED')" is never reached. (Note the @ORM\PreUpdate) This means that lifecycleCallbacks are not called on inherited objects. Is this a bug, or is there a reason for this?

7条回答
别忘想泡老子
2楼-- · 2019-01-14 12:55

Maybe i'm wrong but I don't think preUpdate isn't triggered when you persist an entity. You should have a @prePersist.

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

But still then i'm not sure this is going to work but you could try that. Else a workaround would be to overwrite the setUpdatedAt function and just call his parent one but that's a bit ugly.

Hope the @prePersist helps for you.

查看更多
萌系小妹纸
3楼-- · 2019-01-14 13:07

You have to annotate the base class with @ORM\HasLifecycleCallbacks, and the function with @ORM\preUpdate

You have a typo (PreUpdate should be preUpdate), also preUpdate isn't called on creation (only on update). So if you want it also be triggered on creation, you should add @ORM\prePersist.

查看更多
干净又极端
4楼-- · 2019-01-14 13:10

I think you have to annotate the base class with @ORM\HasLifecycleCallbacks

docs

查看更多
Explosion°爆炸
5楼-- · 2019-01-14 13:14

Your abstract base class has to be anotated as Mapped Superclasses and include the HasLifecycleCallbacks-Annotation.

Further Information: Inheritance Mapping in the Doctrine Documentation.

/**
 * @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.
}
查看更多
做个烂人
6楼-- · 2019-01-14 13:16

While the accepted reply is correct for the general case, in this particular case (timestamp) you actually want to use the doctrine extension Timestampable as explained for example here Lifecycle Callback Issue When Extending FOSUserBundle User Entity

查看更多
\"骚年 ilove
7楼-- · 2019-01-14 13:18

It is important that the MappedSuperclass with HasLifecycleCallbacks is in the same namespace or directory as their child Entities.

I had problems with life cycle callbacks when the MappedSuperclass was in one directory (Model) while the Entities were in another (Entity). Putting the MappedSuperclass in the same directory as the Entities (Entity) solved the issue.

查看更多
登录 后发表回答