Attempt at a better type resolution on Yii::createObject #28
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR attempts to provide more flexibility in the way
Yii::createObject
can be used, by using generic typehints instead of an extension.The current implementation of the extension only allows for a few ways to use
Yii::createObject
:Yii::createObject('\Foo')
will return an instance of\Foo
Yii::createObject(\Foo::class)
will return an instance of\Foo
Yii::createObject('alias')
will return an instance ofalias
. More on this later.Yii::createObject(['class' => '\Foo'])
will return an instance of\Foo
Yii::createObject(function: \Foo {})
will return an instance of\Foo
Anything else will cause the extension to fail so that phpstan will only report an
internal error
.This can be something as simple as this:
By using a stub with generic typehints phpstan can properly resolve variables, method calls, etc.
There is however one problem. As mentioned above, currently it is possible to do something like this:
Yii::createObject('alias')
This works in Yii, because
Yii::createObject()
is just a wrapper forYii::$container->get()
when called with astring
as the first argument. As far as i can tell, this is not documented behavior: https://www.yiiframework.com/doc/api/2.0/yii-baseyii#createObject()-detailBut it works.
This extension currently assumes that the return value of
Yii::createObject('alias')
is an instance of a class calledalias
. This can easily be corrected by properly typehinting at the calling site:However with generics phpstan attempts to resolve the classname and will report an error:
Parameter #1 $type of static method yii\BaseYii::createObject() expects array('class' => class-string<alias>)|(callable(): alias)|class-string<alias>, 'alias' given.
This can not be solved by typehinting on the calling site, however it is possible to just use
Yii::$container->get()
instead. This has the added benefit of resolving properly to the correct return type, if the config file is properly set up.What do you think?