Asked  7 Months ago    Answers:  5   Viewed   35 times

I have this situation:

Abstract Class:

abstract class AbstractBase
{
    /**
     * @ORMId
     * @ORMGeneratedValue
     * @ORMColumn(type="integer")
     * @var integer
     */
    protected $id;

    /**
     * @ORMColumn(type="datetime", name="updated_at")
     * @var DateTime $updatedAt
     */
    protected $updatedAt;

    /**
     * @ORMPreUpdate
     */
    public function setUpdatedAt()
    {
        die('THIS POINT IS NEVER REACHED');
        $this->updatedAt = new DateTime();
    }
}

Concrete Class:

/**
 * @ORMEntity(repositoryClass="EntityRepositoryUserRepository")
 * @ORMTable(name="users")
 * @ORMHasLifecycleCallbacks
 */
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('EntityUser', 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 @ORMPreUpdate) This means that lifecycleCallbacks are not called on inherited objects. Is this a bug, or is there a reason for this?

 Answers

92

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

Further Information: Inheritance Mapping in the Doctrine Documentation.

/**
 * @ORMMappedSuperclass
 * @ORMHasLifecycleCallbacks
 */
abstract class AbstractBase
{
    [...]

    /**
     * @ORMPreUpdate
     */
    public function setUpdatedAt()
    {
        $this->updatedAt = new DateTime();
    }
}

/**
 * @ORMEntity(repositoryClass="EntityRepositoryUserRepository")
 * @ORMTable(name="users")
 */
class User extends AbstractBase
{
    // some fields, relations and setters/getters defined here, these all work as expected.
}
Wednesday, March 31, 2021
 
IcedAnt
answered 7 Months ago
26

See Serializing Entities in doctrine manual: (Everything you save in a session is serialized and deserialized.)

Serializing entities can be problematic and is not really recommended, at least not as long as an entity instance still holds references to proxy objects or is still managed by an EntityManager.

There is a technical limitation that avoid private properties from being serialized when an entity is proxied (lazy-loaded entities are proxied).

This means that you have to avoid using private properties for the entities you want to serialize (use protected entities instead).

Also, if a lazy-loaded entity is not loaded at serialization time, it won't be loadable after de-serialization. So you have to make sure the entity is fully loaded before serializing it.

Wednesday, March 31, 2021
 
Gigamegs
answered 7 Months ago
32

Don't make it harder than it is. A function with the same signature as a virtual function in a base class overrides the base version. Doesn't matter how many bases you have, or whether another base has a virtual function with the same signature. So, yes, this works.

Friday, August 27, 2021
 
Usman Khan
answered 2 Months ago
77

This bug is fixed in Doctrine 2.4

https://github.com/doctrine/doctrine2/issues/2934

Saturday, October 9, 2021
 
mikelovelyuk
answered 2 Weeks ago
55

The syntax for the declaration of metaclasses has changed in Python 3. Instead of the __metaclass__ field, Python 3 uses a keyword argument in the base-class list:

import abc

class AbstractBase(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def must_implement_this_method(self):
        raise NotImplementedError()

Calling d = ConcreteClass() will raise an exception now, because a metaclass derived from ABCMeta can not be instantiated unless all of its abstract methods and properties are overridden (For more information see @abc.abstractmethod):

TypeError: Can't instantiate abstract class ConcreteClass with abstract methods
must_implement_this_method

Hope this helps :)

Thursday, October 14, 2021
 
GameZelda
answered 1 Week ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :