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

FEATURE: Type declaration support for property injection #2782

Merged
merged 2 commits into from
Mar 28, 2022

Conversation

robertlemke
Copy link
Member

@robertlemke robertlemke commented Mar 28, 2022

This change introduces basic support for PHP 7.4 class property types
for property injection.

It allows for using types as follows:

/**
 * @Flow\Inject
 **/
protected LoggerInterface $logger;

In order to allow this syntax, Lazy Property Injection is disabled
when a type is declared. To still use Lazy Property Injection, don't
use a PHP type declaration but a @var annotation:

/**
 * @Flow\Inject
 * @var LoggerInterface
 **/
protected $logger;

If using both (type declaration and @var), it is handled non-lazily.

Lazy Property Injection on properties with type declarations may
be re-implemented as part of a future release.

#2114

This change introduces basic support for PHP 7.4 class property types
for property injection.

It allows for using types as follows:

```php
/**
 * @flow\Inject
 **/
protected ?LoggerInterface $logger;
```

In order to allow this syntax, Lazy Property Injection was disabled
completely. It may be re-implemented as part of a future release.

neos#2114
@robertlemke
Copy link
Member Author

This change is a shortcut / alternative to #2701

@bwaidelich
Copy link
Member

Awesome!
I don't (yet) understand the full code, but I can confirm that this fixes injection with type hints (and without @var annotation).

I would suggest, not to communicate the nullable version though but:

/**
 * @Flow\Inject
 */
protected LoggerInterface $logger;

to make code more resilient and clarify that this is currently not lazily injected.

This is great, and will bring me back to using inject annotations in application code. Thanks! <3

bwaidelich
bwaidelich previously approved these changes Mar 28, 2022
Copy link
Member

@bwaidelich bwaidelich left a comment

Choose a reason for hiding this comment

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

+1 by manual testing (not so much by reading yet)

@kitsunet
Copy link
Member

I am not sure why we would sacrifice one feature (lazy injections) for another (PHP 7.4 property type hint support).

@bwaidelich
Copy link
Member

I am not sure why we would sacrifice one feature (lazy injections) for another (PHP 7.4 property type hint support).

Hang on. I expected this to work as before if I decide to omit the type hint (which is still allowed in all PHP versions)
If this disables lazy DI in any case I would change my vote to -1

@bwaidelich bwaidelich dismissed their stale review March 28, 2022 08:25

Sorry, I misinterpreted the change

Copy link
Member

@kitsunet kitsunet left a comment

Choose a reason for hiding this comment

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

Cool! This seems like a sensible tradeoff I guess, will be interesting to compare performance of a code base written with property type hints and one without.

@robertlemke robertlemke requested a review from bwaidelich March 28, 2022 08:45
@robertlemke robertlemke changed the title !!! Basic support for PHP 7.4 class property types Basic support for PHP 7.4 class property types Mar 28, 2022
Copy link
Member

@albe albe left a comment

Choose a reason for hiding this comment

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

Looks good by reading. Only left a comment for type-hinting the new ReflectionService method

@robertlemke robertlemke changed the title Basic support for PHP 7.4 class property types Type declaration support for property injection Mar 28, 2022
Copy link
Member

@kdambekalns kdambekalns left a comment

Choose a reason for hiding this comment

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

Awesome step into the right direction!

@@ -1315,7 +1331,7 @@ public function reflectClassProperty($className, PropertyReflection $property)
$this->classReflectionData[$className][self::DATA_CLASS_PROPERTIES][$propertyName][self::DATA_PROPERTY_TAGS_VALUES][$tagName] = $tagValues;
}

foreach ($this->annotationReader->getPropertyAnnotations($property, $propertyName) as $annotation) {
Copy link
Member

Choose a reason for hiding this comment

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

Nice one… that parameter was passed since 2013 but not used? Ever? 🤪

@albe
Copy link
Member

albe commented Mar 28, 2022

Another question:

It allows for using types as follows:

/**
 * @Flow\Inject
 **/
protected ?LoggerInterface $logger;

What was the exact reason the nullability was required? It wasn't just the lazyness, because that would mean we don't need it for typed properties since the injection is eager (for now).
"Typed property {x} must not be accessed before initialization" was the PHP error and it's happening when a typed property is accessed that wasn't initialized (in the constructor or declaration). So my question is: do we somewhere in the proxy code or somewhere else attempt to bypass the constructor, or not set the property in the constructor?
Does anyone have the full proxy code for such a class around right now?

@kdambekalns
Copy link
Member

I adjusted the PR description, is that fine for you, @bwaidelich and @robertlemke?

Copy link
Member

@bwaidelich bwaidelich left a comment

Choose a reason for hiding this comment

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

Love it, and I can confirm that

    /**
     * @Flow\Inject
     * @var LoggerInterface
     */
    protected $logger;

injects the DependencyProxy and

    /**
     * @Flow\Inject
     * @var LoggerInterface
     */
    protected LoggerInterface $logger;

(or without the @var annotation) injects the actual logger instance!

Thank you so much! <3

@bwaidelich
Copy link
Member

@kdambekalns

To still use Lazy Property Injection, declare the type as nullable

That's not correct though. When the type hint is specified, we now always fall back to eager injection.

@robertlemke
Copy link
Member Author

What was the exact reason the nullability was required? It wasn't just the lazyness, because that would mean we don't need it for typed properties since the injection is eager (for now).
"Typed property {x} must not be accessed before initialization" was the PHP error and it's happening when a typed property is accessed that wasn't initialized (in the constructor or declaration). So my question is: do we somewhere in the proxy code or somewhere else attempt to bypass the constructor, or not set the property in the constructor?
Does anyone have the full proxy code for such a class around right now?

The error should only occur with lazy loading, so nullability is not required at the moment. And when we have support for union types, it will probably not even be allowed or at least does not make sense.

@robertlemke
Copy link
Member Author

@kdambekalns @bwaidelich I updated the description to correct that.

@kdambekalns
Copy link
Member

@albe asked

What was the exact reason the nullability was required?

It was needed for protected ?LoggerInterface $logger = null; – something not in the example. Obviously I thought about that but missed that this isn't needed anymore…

@kdambekalns
Copy link
Member

I added a hint on using type and @var to the description. Just to be very clear.

@robertlemke
Copy link
Member Author

So, we're all set?

@albe
Copy link
Member

albe commented Mar 28, 2022

So who wants to have the honor of pushing the merge button on this PR we have been all longing for? :) @robertlemke maybe, as he has put in all the hard grunt work.
We (Martin and I) will then branch off 8.0 this (late) afternoon

@albe albe changed the title Type declaration support for property injection FEATURE: Type declaration support for property injection Mar 28, 2022
@robertlemke
Copy link
Member Author

So who wants to have the honor of pushing the merge button on this PR we have been all longing for? :) @robertlemke maybe, as he has put in all the hard grunt work.
We (Martin and I) will then branch off 8.0 this afternoon

LOL, this PR is just a couple of minute's work ;-) Anyway, I'll take the chance.

@robertlemke robertlemke merged commit 2abbebf into neos:master Mar 28, 2022
@robertlemke robertlemke deleted the class-property-fixes-shortcut branch March 28, 2022 09:40
@albe
Copy link
Member

albe commented Mar 28, 2022

LOL, this PR is just a couple of minute's work ;-) Anyway, I'll take the chance.

It sometimes requires a lifetime of work to finally come to the solution that only takes 5 minutes worth of work. That doesn't devalue the lifetime spent before :)

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.

5 participants