0

Background

I've got an entity A with single table inheritance set up and class Foo extending it like so:

/**
 * @ORM\Entity()
 * @ORM\InheritanceType("SINGLE_TABLE")
 * @ORM\DiscriminatorColumn(name="type", type="string")
 * @ORM\DiscriminatorMap(
 *   "foo" = Foo
 * )
 */
abstract class A 
{
  // ...
}

/**
 * @ORM\Entity()
 */
class Foo extends A 
{ 
  // ...
}

This works with no problems. However, I need to be able to let 3rd party code extend A as well. Problem: I don't know the discriminator mappings that would be needed to wire this up beforehand as this is a property of the base class.

My current solution

I'm in Symfony land, so I can make use of the dependency injection container and decorate the annotation_reader* (that processes the discriminator map class annotations) with my own one.

This reader delegates most of the calls to the original one but can extend found discriminator map annotations. It does so based on an 'extension registry' which itself is filled by a compiler pass looking for a special service tag. Anyone wanting to extend the core entity A with Bar can now tag Bar with this service tag (that also includes the identifier for the mapping; the column type in this example).

*) this will probably also work within the loadClassMetadata event - which would be preferable instead of decorating the reader

/**
 * @ORM\Entity()
 * @DiscriminatorMapExtension("bar")
 */
class Bar extends A 
{ 
  // ...
}

(I'm using service annotations in the above example to be able to write the tags directly beneath the entity annotation. But how exactly the classes will be registered in the end doesn't matter right now. I'm more interested in the general concept.)

So if it's working, what's the problem?

I'd really love to hear some feedback from experienced Doctrine devs on this approach, especially:

  • Is there a better way to achieve a 'shared entity' across bundles?
  • Why could this pattern be a problem?

Thanks a lot in advance!

mvo
  • 1,138
  • 10
  • 18
  • Entities are domain objects with state and any entity we write should be domain specific. IMO providing entities to third party code for extending is fundementally bad idea. You or the code relying on your entities may find themselves in a pretty unexpected situations which requires modifying both sides to workaround. I would recommend re-consider the main goal you are trying to achieve and overall design of your application (or library) – edigu Nov 03 '19 at 08:52
  • I appreciate your comment but don't see why extending using STI would be a bad idea - everyone extending the base will have their own entity? Where would you see conflicts? – mvo Nov 03 '19 at 17:02

0 Answers0