since the first introduction of type declarations for arrays and objects back then in PHP 5.3, via type declarations for simple types in PHP 7.0 up to PHP 8.0, which will allow union types, all PHP projects have to choose whether they want to take the duck typing approach (walks like a duck, quacks like a duck, it’s a duck) or the type declaration approach, which strictly defines if a method allows ducks or not.
TYPO3 always chose the latter and since that decision for or against type declaration isn’t up to the discussion, the way and pace are. Less metaphorically speaking: TYPO3 still has dozens of classes, methods and properties without a type declaration and the question is how to change this.
Until now, type declarations have been added to new code and code that has been “hardened” or refactored. When I hardened classes and methods in Extbase in TYPO3 10, I did it patch by patch and had to write a lot of documentation as all those changes were potentially breaking. I did a lot of research last year and looked for a way to ease those migrations and there actually is one called “rector”. Rector is a tool, which performs changes on your code base, based on certain rules. There are hundreds of so called rectors out there to automatically change your code base and one set of those rules is just about type declarations. https://github.com/rectorphp/rector/blob/master/docs/rector_rules_overview.md#typedeclaration
I used rector to perform automated updates on the TYPO3 code base, to check out it’s potential. Rector is still a bit unstable but in general it performs great and it can literally save us days of manual work. There are two patch sets that show the result of using rector on the TYPO3 code base. Both have been done in minutes actually.
What I would like to have as discuss here, is the usage of rector to automatically add type declarations in one single patch to the whole code base.
The pros are:
- When it’s done, it’s done for good.
- It’s potentially breaking, but just once.
- It saves a lot of time doing all that work manually
- We have a more stable code base at once.
The cons are:
- It’s potentially breaking, can and will result in regressions
- It will result in more backporting issues as patches will not be applicable without merge conflicts
I would like to hear your opinion on this topic. What do you think about the pros and cons I listed here? What are pros and cons I didn’t list here? Will this do more harm that it does good or is that a big opportunity to lift up the code base in one go? Let me know in the comments.
I would like to add that extension authors can use rector as well, migrating their own code base in minutes, too. When using XClasses for instance, an author usually wants to override one or several methods while keeping the method signature as is. Using rector, those methods can easily be automatically adjusted to fit the method signature of the original class.
Covariance and contravariance have improved a lot since PHP 7.2 and even more since PHP 7.4. That means, that not all type declaration changes are by default breaking. A more specific type declaration for method params is not an issue as seen here https://3v4l.org/Y7Q4W
In contrast to that, having a less specific return type (or none) will eventually raise an error as seen here https://3v4l.org/3jirO
Here are two patches covering Claus’ approach:
- https://review.typo3.org/c/Packages/TYPO3.CMS/+/64429 (private properties)
- https://review.typo3.org/c/Packages/TYPO3.CMS/+/64430 (protected properties)
Topic Initiator: Alexander Schnitzler
Topic Mentor: tbd