Problem/Motivation
PHP has deprecated \ReflectionParameter::getClass(). We should replace our usages of it:
We use it in:
- ArgumentsResolver
- EntityResolverManager
- ProxyBuilder
- TaggedHandlersPass
Proposed resolution
Add helper to core/lib/Drupal/Component/Utility to handle this. Hopefully this approach will make it easier to backport to Drupal 8 and supporting PHP7 means that we need to still use getClass() there. It's not necessary at all in Drupal 9 since the reflection classes and methods we should use exist since PHP 7.2.
Remaining tasks
None
User interface changes
None
API changes
Calls to \ReflectionParameter::getClass()
should be replaced with \Drupal\Component\Utility\Reflection::getParameterClassName($parameter);
. Note that Reflection::getParameterClassName()
returns the class name as a string and not a \ReflectionClass object.
Data model changes
None
Release notes snippet
In order to be PHP 8 compatible code that uses \ReflectionParameter::getClass()
should use the new utility \Drupal\Component\Utility\Reflection::getParameterClassName()
instead. See
Comment | File | Size | Author |
---|---|---|---|
#27 | 3156542-27.patch | 6.9 KB | alexpott |
#27 | 25-27-interdiff.txt | 578 bytes | alexpott |
Comments
Comment #2
volegerLet's try to get rid of the deprecation message
Comment #3
volegerComment #5
volegerSo it's not break compatibility with currently supported PHP 7 versions. Also no deprecation notices provided in PHP 8 testing log.
Back to needs review.
Comment #6
alexpottSo this is not the only place that we use ReflectionParameter::getClass() but I agree that we should handle each one in an issue like this so we can review and think about what to do in each case.
Comment #7
alexpottComment #8
Ghost of Drupal Pasthttps://stackoverflow.com/q/62705458/308851
Comment #9
alexpott@Charlie ChX Negyesi is #8 pointing out we have a problem with union types?
Comment #10
alexpottI'm thinking actually that #6 is wrong and we should address all the usages of deprecated ReflectionParameter methods together as I think the are a couple of complexities that mean we should add a BC layer that we can call.
Here's all the changes of this ilk that we need from #3156595: Make Drupal 9 installable on PHP8. Now I'm going to add a testable BC layer that also has special handling for 'self' - see https://github.com/phpDocumentor/ReflectionDocBlock/pull/240
Comment #11
alexpottHere's the helper method and test. Unfortunately ProxyBuilder doesn't depend on utility - but also it's usecase is a little more specialised so I think we shouldn't try to use the help anyway. Also the proxy builder changes will have the reasonable side effect of making it handle scalar typehints correctly. So we might want to carve that out into a separate issue to add explicit test coverage anyway.
Comment #12
alexpottComment #13
Ghost of Drupal Past@alexpott yes for union types.
Edit: TranslationManager and combination of various entity interfaces are examples.
Comment #14
alexpott@Charlie ChX Negyesi sure union types are a related issue but it's not necessary to handle them here. They're not possible in PHP 7 so we can't use them in core - so support for them should be a follow-up or maybe just a related issue.
Comment #15
alexpottThis is a bug fix for PHP 8. So it's not a task.
Splitting out the ProxyBuilder changes - #3156944: Support nullable typehints and return types in ProxyBuilder and as a result support PHP 8
Comment #16
Ghost of Drupal PastIf we are writing a helper class anyways, what about:
Comment #17
andypostMeantime core already require
doctrine/reflection
so maybe there's no need to introduce new component?Setting NW because every component require own composer.json file and few text files
Comment #18
Gábor Hojtsy@andypost: hm, I looked at https://www.doctrine-project.org/projects/doctrine-reflection/en/1.2/ref... and don't know what would be useful from there to provide this functionality?
@andypost: is there docs on what a new component requires in core? Tried to find it via google, no luck.
I agree with @Charlie ChX Negyesi that introducing a has* method would help provide the condition part of the method as a separately useful functionality. Making the consumer use the has* method first to avoid getting an exception may not be the best idea. (I am not a Drupal core framework manager though ;)
Comment #19
martin107 CreditAttribution: martin107 as a volunteer commentedComment #20
andypost@Gábor Hojtsy: sorry, I was wrong - this component already defined (
drupal/core-utility
)I like making the class final but interesting how we can get rid of it in future or how we can extend it as no policy accepted yet
There's only one method, and as class defined final - how it expected it can add new methods?
Related #3019332: Use final to define classes that are NOT extension points
it could use a comment about early return
Comment #21
alexpott@andypost we have plenty of final classes in core. Anything static and in component is by design not meant to be extended - as it actually makes no sense. Adding final just enforces this sensibility from a code POV.
Comment #22
alexpottAs far as I can see there is nothing more to do here. Created a CR (https://www.drupal.org/node/3173795) and updated the issue summary.
Re #17 - this is part of the utility component - it is not standalone.
Re #20 Using final and static for classes in component has precedent. The API contract is \Drupal\Component\Utility\Reflection::getParameterClassName() which once we land this patch we won't change. Since the class is final we are free to add more reflection utility methods to this class as we require as nothing can extend it and add other methods. If we decide to get rid of the class then we can deprecate it like any other class / method.
Re #16 I think adding a
hasParameterClassName()
is not worth it. In the code samples in #16 thehasParameterClassName()
will always have to be called before thegetParameterClassName()
. HavinggetParameterClassName()
declare that is can return NULL is more robust.Comment #23
alexpottWe don't use yoda conditions in Drupal...
Comment #24
alexpottIn order to make this backportable to Drupal 8 and PHP 7.0 compat we'd need to do
I don't think we should do this here. But at least the option of backporting this to D8 is there. I've looked at similar changes in Symfony - for example \Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory::getType() (it is private) and \Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper::getTypeHint() (public static) and no of them fit perfectly unfortunately.
We need to cope with parent typehints too :)
Comment #25
alexpottAddressing #2 and borrowing code from \Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory::getType() which is very very similar.
Comment #26
andypostI looks ready except docs
Would be great to ref to https://wiki.php.net/rfc/case-sensitivity
still needs comment, I see this change is not covered in
\Drupal\Tests\Core\Entity\EntityResolverManagerTest
Comment #27
alexpottRe #26.1 I don't understand why linking to a draft RFC helps here. I think it's unnecessary.
Re #26.2 - actually is not part of this and deserves it's own issue. Imo this doesn't need a test. It is all about the internals ... see https://3v4l.org/4oYFT
Comment #28
andypost@alexpott thank you, it explains, needs separate issue, #26.1 is optional cos explains class names are case insensitive
#26.2 issue #3173958: PHP 8 error: method_exists(): Argument #1 ($object_or_class) must be of type object|string, null given
Rtbc +1
Comment #29
andypostIt could use to add remains of https://github.com/doctrine/reflection/pull/43#issuecomment-710255073
Comment #31
tim.plunkettComment #32
longwaveLGTM. I agree that neither point in #26 needs fixing here. Looks like we might need more similar issues to replace the Doctrine component in the near future though.
Comment #34
catchThis looks good to me. Worst case is if we have to home-grow a replacement for Doctrine Reflection, we might eventually want to move the code around, but it's one static method so easy to do that if we ever wanted to.
Comment #37
donquixote CreditAttribution: donquixote as a volunteer commentedFor union types there is now this new issue:
#3315276: Fatal error when using a union type on a controller's callback
Comment #38
quietone CreditAttribution: quietone at PreviousNext commentedPublish the CR