-
-
Notifications
You must be signed in to change notification settings - Fork 188
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
Full support for PHP 7.4 property type declarations #2114
Comments
Something like this should do the trick (still missing backwards compatibility for PHP < 7.4): Index: Neos.Flow/Classes/Reflection/ReflectionService.php
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- Neos.Flow/Classes/Reflection/ReflectionService.php (date 1599581621814)
+++ Neos.Flow/Classes/Reflection/ReflectionService.php (date 1599581621814)
@@ -89,6 +89,7 @@
const DATA_METHOD_DECLARED_RETURN_TYPE = 25;
const DATA_PROPERTY_TAGS_VALUES = 14;
const DATA_PROPERTY_ANNOTATIONS = 15;
+ const DATA_PROPERTY_TYPE = 16;
const DATA_PROPERTY_VISIBILITY = 24;
const DATA_PARAMETER_POSITION = 16;
const DATA_PARAMETER_OPTIONAL = 17;
@@ -977,6 +978,11 @@
return (isset($this->classReflectionData[$className][self::DATA_CLASS_PROPERTIES][$propertyName][self::DATA_PROPERTY_TAGS_VALUES][$tag])) ? $this->classReflectionData[$className][self::DATA_CLASS_PROPERTIES][$propertyName][self::DATA_PROPERTY_TAGS_VALUES][$tag] : [];
}
+ public function getPropertyType($className, $propertyName)
+ {
+ return $this->classReflectionData[$className][self::DATA_CLASS_PROPERTIES][$propertyName][self::DATA_PROPERTY_TYPE] ?? null;
+ }
+
/**
* Tells if the specified property is private
*
@@ -1280,6 +1286,9 @@
$visibility = $property->isPublic() ? self::VISIBILITY_PUBLIC : ($property->isProtected() ? self::VISIBILITY_PROTECTED : self::VISIBILITY_PRIVATE);
$this->classReflectionData[$className][self::DATA_CLASS_PROPERTIES][$propertyName][self::DATA_PROPERTY_VISIBILITY] = $visibility;
+ if ($property->hasType()) {
+ $this->classReflectionData[$className][self::DATA_CLASS_PROPERTIES][$propertyName][self::DATA_PROPERTY_TYPE] = (string)$property->getType();
+ }
foreach ($property->getTagsValues() as $tagName => $tagValues) {
$tagValues = $this->reflectPropertyTag($className, $property, $tagName, $tagValues);
@@ -1289,7 +1298,7 @@
$this->classReflectionData[$className][self::DATA_CLASS_PROPERTIES][$propertyName][self::DATA_PROPERTY_TAGS_VALUES][$tagName] = $tagValues;
}
- foreach ($this->annotationReader->getPropertyAnnotations($property, $propertyName) as $annotation) {
+ foreach ($this->annotationReader->getPropertyAnnotations($property) as $annotation) {
$this->classReflectionData[$className][self::DATA_CLASS_PROPERTIES][$propertyName][self::DATA_PROPERTY_ANNOTATIONS][get_class($annotation)][] = $annotation;
}
Index: Neos.Flow/Classes/ObjectManagement/Configuration/ConfigurationBuilder.php
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- Neos.Flow/Classes/ObjectManagement/Configuration/ConfigurationBuilder.php (date 1599581727458)
+++ Neos.Flow/Classes/ObjectManagement/Configuration/ConfigurationBuilder.php (date 1599581727458)
@@ -555,7 +555,13 @@
if (!array_key_exists($propertyName, $properties)) {
/** @var Inject $injectAnnotation */
$injectAnnotation = $this->reflectionService->getPropertyAnnotation($className, $propertyName, Inject::class);
- $objectName = $injectAnnotation->name !== null ? $injectAnnotation->name : trim(implode('', $this->reflectionService->getPropertyTagValues($className, $propertyName, 'var')), ' \\');
+ $objectName = $injectAnnotation->name;
+ if ($objectName === null) {
+ $objectName = $this->reflectionService->getPropertyType($className, $propertyName);
+ }
+ if ($objectName === null) {
+ $objectName = trim(implode('', $this->reflectionService->getPropertyTagValues($className, $propertyName, 'var')), ' \\');
+ }
$configurationProperty = new ConfigurationProperty($propertyName, $objectName, ConfigurationProperty::PROPERTY_TYPES_OBJECT, null, $injectAnnotation->lazy);
$properties[$propertyName] = $configurationProperty;
}
|
But be careful when using typed properties: They cannot be lazy (the proxy never fits the required type) and they must not be accessed before being initialized. Both facts represent problems, as I learned in a project (when using In short: There's more needed than simply reading the intended type from the declaration. |
Thanks for the heads-up!
You're right, I updated the example |
Sure? |
The LazyLoadingProxy, not the „usual“ proxy…
… Am 25.09.2020 um 19:13 schrieb Alexander Berl ***@***.***>:
They cannot be lazy (the proxy never fits the required type)
Sure?
https://3v4l.org/8R1vD
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or unsubscribe.
|
This is the case Karsten was referring to (I assume): https://3v4l.org/4UtYu -> The properties that are injected via |
Well, that's one thing. The other is that for a lazy-loading objects we use a |
Folks, can we do anything to progress this? i.e. start with a PR with the above diff and start adding helpful error message during compile step with injections into typed properties? |
Thinking some more about this, the issue with lazy DependencyProxy and typehints is, that the proxy does not extend the actual class. We could solve that by
The latter would complement #1835, which would also require our current DI proxies (the classes that are injected into) to be changed to use proxymanager (or use a proper PHP parser). Drawback: we'd depend on proxymanager/lamanias-code to add support for e.g. new PHP8 features, but OTOH we gain some additional developer power in that department. |
Having the proxies fulfill |
I'd also like to have a look at this, hopefully during the sprint next week in Dresden. |
As agreed upon during the sprint meeting, we will go with solution 1 for the reasons given in #1835 (comment) Things noticed during the call:
Robert has a base that he will create a PR for next and then we can work it out. |
This change adjusts the proxy building and dependency injection process to properly handle PHP 7.4 class property type declarations. neos#2114
This change adjusts the proxy building and dependency injection process to properly handle PHP 7.4 class property type declarations. neos#2114
Good news, I think I have solved it (see related pull request). |
This change adjusts the proxy building and dependency injection process to properly handle PHP 7.4 class property type declarations. neos#2114
In order to find a shortcut, I tried @bwaidelich's original suggestion again. But even if I disable lazy injection completely, I still get an error:
Relevant code: /**
* @Flow\Inject(lazy=false)
*/
protected ?TestSingleton $testSingleton = null; |
You get the error with the /**
* @Flow\Inject(lazy=false)
*/
protected ?TestSingleton $testSingleton; should even work if the dependency is resolved within the constructor call |
Ah, sorry, it's the other property, logger: /**
* LoggerInterface doesn't have to be nullable, because the proxy class
* builder will not even try to use lazy injection, since it is an interface
**/
protected LoggerInterface $logger;
/**
* @Flow\Inject(lazy=false)
*/
protected ?TestSingleton $testSingleton = null; |
It works this way: /**
* LoggerInterface doesn't have to be nullable, because the proxy class
* builder will not even try to use lazy injection, since it is an interface
*
* @Flow\Inject(lazy=false)
**/
protected ?LoggerInterface $logger = null;
/**
* @Flow\Inject(lazy=false)
*/
protected ?TestSingleton $testSingleton = null; |
Interesting, how does the resulting proxy code look like? |
can we maybe work around that the lazy proxy needs to fulfill
|
@mhsdesign that's what I suggested as well https://neos-project.slack.com/archives/C050KKBEB/p1648453577172009?thread_ts=1648224274.563979&cid=C050KKBEB :) But IMO /**
* @Flow\Inject
**/
protected LoggerInterface $logger; should work, too (without proxy). @robertlemke in your example no inject annotation exists!? |
oooh, good catch, is that injected via inject annotation? |
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
I created a separate pull request (see above). Let's check if that is sufficient for now. |
FEATURE: Type declaration support for property injection 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 is disabled when a type is declared. To still use Lazy Property Injection, don't use a PHP type declaration but a `@var` annotation: ```php /** * @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
Alright, I guess we can close this and tackle lazy injection support for typed properties in a separate issue. |
Description
Since version 7.4 PHP supports type declarations, see RFC but we don't respect those in our ReflectionService, so the following won't work:
The text was updated successfully, but these errors were encountered: