Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Doctrine 2 LifecycleCallbacks with abstract base class are not called

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?

like image 677
smoove Avatar asked Sep 06 '11 13:09

smoove


3 Answers

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.
}
like image 123
Benjamin Cremer Avatar answered Nov 01 '22 14:11

Benjamin Cremer


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.

like image 45
n2o Avatar answered Nov 01 '22 14:11

n2o


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

like image 2
dbu Avatar answered Nov 01 '22 13:11

dbu