Introduce doctrine/annotations as a replacement for custom anntations

Hi friends,

during my research on how to reduce the codebase of Extbase to a minimum, I came across the whole Reflection and DependencyInjection parts and I quickly realized that the way Extbase does things is a bit chaotic and hard to solve with 3rd party libraries.

I tried to see if we can use libraries such as symfony/property-info, symfony/property-access that rely on great libraries like phpdocumentor/reflection and nikic/php-parser themselves to have less own code that does magic the Extbase way.

No matter what I tried, I realised that all these libraries are very good and do a brilliant job as long as you stick to the rules, mainly, only using the official annotations for php doc blocks like @var, @param and such. Unfortunately, Extbase doesn’t comply.

Let’s have an example:
Extbase has a ReflectionService that analyses all classes for several reasons. There is Dependency Injection, which relies on annotations like @inject, then there is the validation with @validate, @ignorevalidation and such. There’s also the property mapper part and of course the whole ORM that abuses @param and introduces annotations like @lazy and such.

The problem is: If we want to reduce the code of Extbase in current state, we have to teach the 3rd-party-libraries all the dirty ways Extbase does things. That’s when I realized, we need to have a look at the bigger picture here.

My proposal is as follows:

As a first step we could migrate all the custom annotations to doctrine annotations. That way, we define these custom annotations with actual classes. If you played around with flow or symfony, you are used to them. The good thing about these annotations is, that they have a context. Please have a short look at https://review.typo3.org/#/c/54327/ to see a very basic replacement of @inject. When you look at the patch and the use statement in the QueryFactory you can see, that you get a context from the namespace of the annotation. Using @Extbase\DependencyInjection\Inject instead of @inject is a lot more self-explanatory. Also, one can have a look at the class that defines the annotation and sees how it’s to be used.

Like prefixing the Inject with DependencyInjection, we could prefix all custom annotations according to their origin.
Imagine having an @Extbase\ORM\OneToMany<Foo> instead of @param ObjectStorage<Foo> or an @Extbase\Validation\Assert\NotEmpty instead of @validate NotEmpty. Not only is it a lot clearer what these annotations do and what part of software they are from and for, they bring us also closer to the usage of other frameworks.

Furthermore it’s a small step from @Extbase\Validation\Assert\NotEmpty to Symfony\Component\Validator\Constraints\Assert\NotEmpty and we are very close to replace all our own logic with the one of a 3rd-party-validation library. Well, that’s just one idea of many. We are also a lot closer to @Doctrine\ORM\Mapping\ORM\Entity and so on. You get the gist.

How to proceed?

Well, until the release of 9LTS, all annotations need to be reimplemented using doctrine annotations. Then, the usage of all current annotations become deprecated and as of 10LTS people need to have their code ready to use doctrine annotations exclusively. Afterwards, we can start cleaning up Extbase’s code, that deals with doc block analysis.

It’s a job that will last for several LTS version but I think we have a good chance getting things done quickly as soon as we decide to proceed in that direction.

So, what do you think?

14 Likes

Really nice research.

I think the Validators might be a very good first step in this direction. Basically, deprecating all existing validators and use third-party validators (if possible) or create customer classes for that that can be called.

Going with
a) introducing new annotations the proper way to enable ext authors to use them (while keeping the old ones, so ext authors define both @inject And @Extbase/Inject)
b) deprecating old annotations

Can both be achieved with TYPO3 v9. Validators and DI annotations (inject, lazy) are the first on the list. Looking into the ObjectStorage might get more complicated I could imagine, but at some point we have to deal with that.

Any chance this feature can be backported to TYPO3 v8 with a lowlevel PHP library which people could adapt?

Apart from that: +1 on doing that as soon as possible.

Hello there,

great proposal - introducing doctrine/annotations (which are already an implicit dependency through doctrine/common and shipped with TYPO3 CMS as of today already) has great potential of reducing the amount of custom code in the TYPO3 core. - Not only in the validation space, but also the class metadata cache could profit significantly in a later step.

Speaking of validation: We should contemplate whether we want multiple mapping formats for validation (in terms of symfony/validator) since f.e. the yaml validation mapping allows for greater flexibility for 3rd party developers throughout customizing validation of an entity.

Thx for bringing this up - +1 from my side.

I’m generally in favor of using more commonly used libraries/features from the PHP world.

What about the performance of injection via annotation compared to method injection? The former being slow was the reason why TYPO3 has migrated to method injection everywhere.

@mbrodala i think the property injection annotation was just meant to be an example of how the porting for annotation would work out. - Yes, property injection is slower since it’s done through reflection, but I would generally like to keep it - not just for historical reasons, but also since it’s one one of the three generally used injection types in OOP (constructor/method/field). If I was to choose, I’d plead for constructor injection only, since IMHO it’s the only valid entry point in the lifecycle of an object, but I still think it’s important to give people choices about how they create their objects.

BTW: The PhpStorm / IntelliJ plugin provides a quickfix for field injections (to method injection) and an inspection for property injection which marks it as a smell and gives a quick message about it being slower. I created it in the hope to keep people away from property injection.

2 Likes

Exactly. This is no discussion about @inject vs injectFoo methods. It’s about replacing custom annotations in general.

I like the proposal, just wanted to add, that I’d suggest to start with migrating the validators and leaving the DI in place as I’d like to see the Extbase DI replaced with Doctrine DI throughout the core in the long run - but that’d be another discussion :wink:

Sure thing. I don’t want to remove any functionality at first. Just create the possibility to use doctrine annotations instead of the current one but leaving the logic behind all that intact. It just enables us to replace several parts more easily than before. :slight_smile:

2 Likes

This topic was automatically closed after 28 days. New replies are no longer allowed.