Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add runtime validation that the discriminator map contains all entity classes, also abstract ones? #10389

Closed

Conversation

mpdude
Copy link
Contributor

@mpdude mpdude commented Jan 12, 2023

A general decision needs to be made here.

This PR adds a runtime metadata check, requiring all entity classes – including abstract intermediate ones – to be listed in the Discriminator Map (DM).

Why?

#8378 (with a fix in #8903) added this requirement to the SchemaValidator tool.

At least #8736 and #9095 pointed out this was a policy change. #9096 briefly removed the requirement for listing abstract entities, but #9142 opposed and put the check back in.

If we think that it is necessary to have all classes in the DM to ensure correct ORM behaviour, then this should not only be checked by the SchemaValidator tool, but instead deserves a runtime check in the ClassMetadataFactory.

Reasons for this requirement

The pro arguments are somewhat sketchy.

Having all classes in the discriminator map is important for some operations.

I even found a case [in the schema generation tool] when the behaviour is unexpected if the abstract class in the middle of hierarchy is not present

A failing test for that was provided in #9145 as POC, #10387 might be a fix.

That problem goes away when the abstract class is included in the DM (shown in #10388), but it may well be a real issue in its own right.

Reasons against the requirement

  • Since no instances of abstract entities can be created, the corresponding value from the DM is never actually used. Users would be required to put in a dummy discriminator value.

  • Doctrine could/should be able to figure out abstract intermediate entity classes by itself, given that all relevant leaf classes are listed in the DM.

  • Archaeological research as follows

Runtime validation of DM requirements was already in place, with abstract classes being explicitly exempted.

if (
! $class->reflClass->isAbstract()
&& ! in_array($class->name, $class->discriminatorMap, true)
) {
throw MappingException::mappedClassNotPartOfDiscriminatorMap($class->name, $class->rootEntityName);
}

That goes back to 5ff44b5 where DM checking was initially added (corresponding issues #1809, #1810).

The exemption for abstract classes was added briefly afterwards in a0a81db.

Until today, the exception thrown for an incomplete DM explicitly mentions abstract entity classes as an option:

public static function mappedClassNotPartOfDiscriminatorMap($className, $rootClassName)
{
return new self(
"Entity '" . $className . "' has to be part of the discriminator map of '" . $rootClassName . "' " .
"to be properly mapped in the inheritance hierarchy. Alternatively you can make '" . $className . "' an abstract class " .
'to avoid this exception from occurring.'
);
}

Consequences

Merging

  • Will cause breakage for users with "misconfigured" DMs. They may complain, pointing to our own exception suggesting abstract entity classes in the past.
  • Even some of our own tests break due to the discouraged pattern being used
  • Will require extra DM entries that are meaningless to users; maybe schema updates are necessary? (DM values as ENUMs and the like?)
  • Will solve or at least mask some issues – they could be rejected as invalid
  • Will improve consistency between the Schema Validator tool and runtime checks
  • Slight documentation updates should be made to explain the need

Not merging

To-Do

👇🏻 What do you think about this – Merge (:+1:) or do not merge (:-1:)?

@mpdude mpdude changed the title Add runtime validation that the discriminator map contains all entity classes, also abstract ones Add runtime validation that the discriminator map contains all entity classes, also abstract ones 🤔❓ Jan 12, 2023
Comment on lines +271 to +273
if (! in_array($class->name, $class->discriminatorMap, true)) {
throw MappingException::mappedClassNotPartOfDiscriminatorMap($class->name, $class->rootEntityName);
}
Copy link
Contributor Author

@mpdude mpdude Jan 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This extra check is needed here to catch inheritance roots missing in the DM.

@mpdude
Copy link
Contributor Author

mpdude commented Jan 13, 2023

@beberlei I know you are short on time, but since you authored the core feature a decade ago, your assessment would be highly valued.

@mpdude mpdude deleted the enforce-also-abstract-classes-in-dm branch January 17, 2023 19:39
@mpdude mpdude changed the title Add runtime validation that the discriminator map contains all entity classes, also abstract ones 🤔❓ Add runtime validation that the discriminator map contains all entity classes, also abstract ones? Jan 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant