Doctrine extends essence

I am using Symfony with the Doctrine.

To solve the problem, I want:

  • or When I extend the Entity class, I want the doctrine to ignore the annotation of the @entity parent class (to see it as @MappedSuperclass)
  • or (this is the preferred option). When I extend the Entity class, add something like @MappedChildclass to the child class to know that this class is Entity, but the actual implementation and mappings in the parent class

Let's look at a specific problem:

I have 3 packages:

  • AppBridgeBundle
  • Userbundle
  • Profilebundle

UserBundle and UserProfile should be separated. AppBridgeBundle is a bridge between two packages, it will connect both.

UserBundle has UserEntity :

/** * @ORM\Entity **/ class UserEntity { /** * @var \Acme\UserBundle\Interfaces\ProfileData * @ORM\ManyToOne(targetEntity="Acme\UserBundle\Interfaces\ProfileData", cascade={"persist"}) * ) */ private $profileData; // ... } 

UserBundle has its own ProfileData interface (untied, we only need to implement the implementation of this interface).

ProfileBundle has ProfileEntity :

 /** * @ORM\Entity **/ class ProfileEntity implements Acme\ProfileEntity\Interfaces\Profile { // properties ... } 

Profile The bundle has its own interface profile (untethered).

Basically, the ProfileData and profile interfaces are the same.

The AppBridgeBundle now introduces the Adapter of Profile and ProfileData interfaces for customizing the UserBundle using the ProfileBundle.

 class ProfileAdapter extends \Acme\ProfileBundle\Entity\ProfileEntity implements \Acme\UserBundle\Interfaces\ProfileData, \Acme\ProfileBundle\Interfaces\Profile { } 

Then we add the implementation of the interface to the config.yml application config.yml :

 orm: resolve_target_entities: Acme\UserBundle\Interfaces\ProfileData: Acme\AppBridgeBundle\Entity\ProfileAdapter 

Now the problem is that when I update the doctrine scheme, it causes an error that Acme\AppBridgeBundle\Entity\ProfileAdapter not an entity.

  • If I tag ProfileAdapter with @Entity then it will create two separate tables - I don't need it

  • If I mark the ProfileAdapter using @Entity with the same name as ProfileEntity - @Table('profileentity') , then it gives me an error message table profile already exists

  • If I flag ProfileEntity with @ORM\MappedSuperclass and remove @Entity annotations from it, I will lose the standard implementation of the ProfileEntity class (so it can no longer work without a bridge).

  • if I tag ProfileEntity with @InheritanceType("SINGLE_TABLE") , it will add an unnecessary discriminator field to my table in the table.

Any suggestions?

+4
source share
2 answers

I think the trick is to use the doctrine dispatched loadClassMetadata event. You can track this event with a subscriber who knows ProfileEntity inheritance and insert the @Entity or @MappedSuperclass annotation.

You can see the implementation here: https://github.com/victoire/CmsBundle/blob/master/EventSubscriber/LoadMetadataSubscriber.php In this example, I dynamically inject widgets into the discriminant map of my Widget object. I allow you to adapt this code to your needs.

0
source

Had the same problem as me using your example:

  • move \Acme\ProfileBundle\Entity\ProfileEntity to \Acme\ProfileBundle\Model\ProfileEntity
  • redeclare ProfileEntity class to abstract , but leave all ORM instructions intact
  • redeclare ProfileAdapter to extend the new ProfileEntity model
  • mark ProfileAdapter only @ORM\Entity , all other @ORM* instructions are left in the model class

Pros:

  • no additional tables
  • no additional fields
  • can work without a bridge

Minuses:

  • you must create an entity that extends the abstract model for each new Bundle installation.
0
source

Source: https://habr.com/ru/post/1488256/


All Articles