Skip to content

Ensure classes using the #[Entity] attribute are not declared as service #1868

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

Merged
merged 1 commit into from
Mar 17, 2025

Conversation

GromNaN
Copy link
Member

@GromNaN GromNaN commented Feb 6, 2025

In order to enable discovery of entity classes by the Symfony DIC, we need to exclude them from being registered as actual services.

@stof
Copy link
Member

stof commented Feb 10, 2025

this should also exclude MappedSuperclass and Embeddable

@GromNaN
Copy link
Member Author

GromNaN commented Mar 17, 2025

It's being done in the FrameworkBundle symfony/symfony#59987, but I think that's still valuable to add this in DoctrineBundle as that ease maintenance (if new attributes are added). At some point in the future, they can be removed from the FrameworkBundle: when all the versions of the DoctrineBundle that are supported by FrameworkBundle will have this exclusion.

@ostrolucky ostrolucky merged commit a91383d into doctrine:2.14.x Mar 17, 2025
12 checks passed
@ostrolucky ostrolucky added this to the 2.14.0 milestone Mar 17, 2025
@ostrolucky
Copy link
Member

Can you check errors here https://github.com/doctrine/DoctrineBundle/actions/runs/13908353031/job/38916534370 ? They seem related

@GromNaN
Copy link
Member Author

GromNaN commented Mar 18, 2025

nicolas-grekas added a commit to symfony/symfony that referenced this pull request Mar 21, 2025
…nfiguration callbacks on the same class (GromNaN)

This PR was squashed before being merged into the 7.3 branch.

Discussion
----------

[DependencyInjection] Enable multiple attribute autoconfiguration callbacks on the same class

| Q             | A
| ------------- | ---
| Branch?       | 7.3
| Bug fix?      | yes
| New feature?  | yes
| Deprecations? | yes
| Issues        | Fix doctrine/DoctrineBundle#1868 (comment)
| License       | MIT

Replace #60001

By having a list of callables for each attributes, we can enable merging definitions each having an autoconfiguration for the same attribute class. This is the case with the `#[Entity]` attribute in DoctrineBundle and FrameworkBundle.

I have to deprecate `ContainerBuilder::getAutoconfiguredAttributes()` as its return type is `array<class-string, callable>`; so I added a new method `AttributeAutoconfigurationPass` that returns `array<class-string, callable[]>` in  in order to use reflection on each callable in the compiler pass.

Commits
-------

e36fe60 [DependencyInjection] Enable multiple attribute autoconfiguration callbacks on the same class
@janklan
Copy link

janklan commented Apr 7, 2025

Hello all. I did a minor version upgrade of DoctrineBundle, and my app broke because of this change. The entities could have been part of the DI container for ages (assuming the ../src/Entity path was removed from the default exclusion list in the services.yaml file) and now they're not.

Wouldn't that be considered a BC break?

@GromNaN
Copy link
Member Author

GromNaN commented Apr 7, 2025

I assume you are using findTaggedServiceIds.

By adding the container.excluded tag, this definitions are no longer returned. You need to loop over all the service definitions as done for the #[JsonStreamable] attribute with json_streamer.streamable tag: https://github.com/symfony/symfony/blob/f047c9a3cd81745c16833f98001fe1c8d9e5f9e1/src/Symfony/Component/JsonStreamer/DependencyInjection/StreamablePass.php#L33

@ostrolucky
Copy link
Member

Wouldn't that be considered a BC break?

Not the kind where we guarantee a BC for. Fixes break applications too, if you rely on buggy behaviour.

@janklan
Copy link

janklan commented Apr 7, 2025

Wouldn't that be considered a BC break?

Not the kind where we guarantee a BC for. Fixes break applications too, if you rely on buggy behaviour.

Hmm. I don't think we should just call a long-standing practice a "buggy behaviour" and change it without any warning. Doing so undermines perceived reliability of the BC promise, I think.

It's a behaviour, buggy or not. It is now considered obsolete. I think it should be marked deprecated and then phased out like any other obsolete behaviour.

@ostrolucky
Copy link
Member

I don't think we should just call a long-standing practice a "buggy behaviour" and change it without any warning.

Long standing practice is to have Entities excluded from service container, I don't think you should ignore that either. That really smells like an oversight in your application.

Doing so undermines perceived reliability of the BC promise

Service definitions are not covered by Symfony BC promise. And DoctrineBundle does not officially follow Symfony BC promise anyways.

it should be marked deprecated and then phased out like any other obsolete behaviour.

I don't see any meaningful way to deprecate this without disrupting large portion of the ecosystem, do you?

@janklan
Copy link

janklan commented Apr 7, 2025

Long standing practice is to have Entities excluded from service container

I agree with that. Another part of the long-standing practice was that you could change it, and now you can't.

smells like an oversight in your application

Including entities in the container might be a bad call if it was used to turn Entities into classes with things autowired into them. I didn't include them for that purpose and explained my reasons here.

Service definitions are not covered by Symfony BC promise

I didn't know that

And DoctrineBundle does not officially follow Symfony BC promise anyways.

Fair enough.

I don't see any meaningful way to deprecate this without disrupting large portion of the ecosystem, do you?

TL;DR: Can't you at least throw a warning while compiling the container that the entities are now forcefully excluded?

Full reply: I found this because our CI/CD pipeline started failing: one of the fixtures generators was inserting a null value into a not-null column. The value is auto-generated by an insert trigger. For some reason, the trigger was not firing. Looking closer, the trigger wasn't there at all.

After some stumbling around, I found the custom queries were not executed during the migration process, and the reason for that was that the migration listener responsible for finding the entities and executing their custom queries was no longer receiving their list from the container.

Things were still working fine on previously deployed systems because all of the custom stuff was already set up. I think that's a pretty stealthy bug.

If there was any sort of warning, I'd probably say "Oh, yeah, no worries".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants