不调用具有抽象基类的Doctrine 2 LifecycleCallbacks

时间:2022-02-12 00:33:10

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?

一切都按预期工作,所以抽象类的id字段是为User实体创建的,我可以访问它等等。问题是,从未达到“die('这个点永远不会达到')”这一行。 (注意@ORM \ PreUpdate)这意味着不会在继承的对象上调用lifecycleCallbacks。这是一个错误,还是有原因的?

7 个解决方案

#1


32  

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

您的抽象基类必须作为Mapped Superclasses进行分配并包含HasLifecycleCallbacks-Annotation。

Further Information: Inheritance Mapping in the Doctrine Documentation.

更多信息: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


3  

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

您必须使用@ORM \ HasLifecycleCallbacks注释基类,并使用@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.

您有一个拼写错误(PreUpdate应该是preUpdate),也不会在创建时调用preUpdate(仅在更新时)。因此,如果您希望它也在创建时触发,您应该添加@ORM \ prePersist。

#3


2  

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

虽然接受的答复对于一般情况是正确的,但在这种特定情况下(时间戳),您实际上想要使用学说扩展名Timestampable,例如此处解释扩展FOSUserBundle用户实体时的生命周期回调问题

#4


1  

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

也许我错了,但我认为当你坚持一个实体时不会触发preUpdate。你应该有一个@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.

但是,我仍然不确定这会起作用,但你可以试试。另外一个解决方法是覆盖setUpdatedAt函数并调用他的父函数,但这有点难看。

Hope the @prePersist helps for you.

希望@prePersist帮助你。

#5


1  

Perhaps you could this issue report as a reference how to setup your annotations? The testcase seems to be valid and matches your use case.

也许您可以将此问题报告作为参考如何设置注释?测试用例似乎有效并且与您的用例相匹配。

#6


1  

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

具有HasLifecycleCallbacks的MappedSuperclass与其子实体位于相同的名称空间或目录中非常重要。

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.

当MappedSuperclass在一个目录(Model)中而实体在另一个目录(Entity)中时,我遇到了生命周期回调的问题。将MappedSuperclass放在与Entities(Entity)相同的目录中解决了这个问题。

#7


0  

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

我认为你必须使用@ORM \ HasLifecycleCallbacks来注释基类

docs

#1


32  

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

您的抽象基类必须作为Mapped Superclasses进行分配并包含HasLifecycleCallbacks-Annotation。

Further Information: Inheritance Mapping in the Doctrine Documentation.

更多信息: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


3  

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

您必须使用@ORM \ HasLifecycleCallbacks注释基类,并使用@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.

您有一个拼写错误(PreUpdate应该是preUpdate),也不会在创建时调用preUpdate(仅在更新时)。因此,如果您希望它也在创建时触发,您应该添加@ORM \ prePersist。

#3


2  

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

虽然接受的答复对于一般情况是正确的,但在这种特定情况下(时间戳),您实际上想要使用学说扩展名Timestampable,例如此处解释扩展FOSUserBundle用户实体时的生命周期回调问题

#4


1  

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

也许我错了,但我认为当你坚持一个实体时不会触发preUpdate。你应该有一个@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.

但是,我仍然不确定这会起作用,但你可以试试。另外一个解决方法是覆盖setUpdatedAt函数并调用他的父函数,但这有点难看。

Hope the @prePersist helps for you.

希望@prePersist帮助你。

#5


1  

Perhaps you could this issue report as a reference how to setup your annotations? The testcase seems to be valid and matches your use case.

也许您可以将此问题报告作为参考如何设置注释?测试用例似乎有效并且与您的用例相匹配。

#6


1  

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

具有HasLifecycleCallbacks的MappedSuperclass与其子实体位于相同的名称空间或目录中非常重要。

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.

当MappedSuperclass在一个目录(Model)中而实体在另一个目录(Entity)中时,我遇到了生命周期回调的问题。将MappedSuperclass放在与Entities(Entity)相同的目录中解决了这个问题。

#7


0  

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

我认为你必须使用@ORM \ HasLifecycleCallbacks来注释基类

docs