Hey, thanks for bringing this up.
I think we need to differentiate between services and data objects.
So, we provide XCLASSES for both types, service classes (controllers, repositories, utilities…) and for data objects (e.g domain models).
On the one hand our service management improved alot via Services.yaml/php configuration and while we may discuss documentation, I think yes, service configuration is the right place for service overrides and a better, non global and side-effect free approach than XCLASSES.
I have to point out a disclaimer though, service overrides should ideally be implemented as decorators, or should at least not overwrite the constructor (as constructor parameters may change for new dependencies).
…but I didn’t test https://symfony.com/doc/5.2/service_container/service_decoration.html with our symfony DI integration yet, as that feature was not available when I integrated symfony 4.x DI.
It’s actually important to rather use decorators instead of simply exending classes as our DI constructors are thus likely to break overwritten services during updates (e.g. think of security updates that require new dependencies for some services), otherwise users don’t really gain anything by migrating away from XCLASSES, besides syntax sugar.
And just to stress that this is still the “right” thing to use the service configuration:
service overrides are also considered in the service-provider container-interop working draft: https://github.com/container-interop/service-provider#entry-overriding (providing support for both, full overriding and full decoration).
Therefore yes, I fully agree that we should officially recommend to configure service overrides via Service.yaml/php configuration and should deprecate XCLASSES in v11, but we should not recommend alias
ing, but rather decoration of services (mostly interface implementations) if possible, and only otherwise aliases…
On the other hand we do not have an nice alternative to XCLASSES for extending/overwriting data object classes, and I actually don’t see a nice alternative. We just removed the extbase-native way and rather recommended to use XCLASSES: https://docs.typo3.org/c/typo3/cms-core/master/en-us/Changelog/10.4/Deprecation-90803-DeprecationOfObjectManagergetInExtbaseContext.html
While I personally try to avoid XCLASSES for data objects (rather use composer patches, which fail during composer update, rather than runtime), I see the usecase for some and therefore would really actually leave this as “feature” for data objects.
To summarise:
I agree to deprecate XCLASSES for services, but would like to recommend/educate a more solid approach decorator approach.
I thus recommend to throw a deprecation if an XCLASS is configured for a Service (technically that means only in GeneralUtility::makeInstanceForDi
– which is called when a service is instantiated via the container).
I would not throw a deprecation for data objects, and simply leave xclasses as in for regular GeneralUtility::makeInstance()
.
Note, this goes in line with future plans to make less and less use of GeneralUtility::makeInstance()
for Services/Singletons in favor of dependency injection, in order to really only use GeneralUtility::makeInstance()
for new data instances and to longer misuse that as service/singleton container. Therefore its good if we now separate class overrides for services and data objects into two different mechanisms.