Back to Phpstan

Closure Extensions

website/src/developing-extensions/closure-extensions.md

2.1.543.5 KB
Original Source

Parameter Closure Type

Sometimes, you might want to change the type of a closure parameter to a function or method call based on the context. For example, the closure might have a generic argument, and you want to change the inner type.

You can create an extension that implements MethodParameterClosureTypeExtension:

php
use PhpParser\Node\Expr\MethodCall;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\ParameterReflection;

interface MethodParameterClosureTypeExtension
{
 public function isMethodSupported(
  MethodReflection $methodReflection,
  ParameterReflection $parameter,
 ): bool;
 
 public function getTypeTypeFromMethodCall(
  MethodReflection $methodReflection,
  MethodCall $methodCall,
  ParameterReflection $parameter,
  Scope $scope,
 ): ?Type;
}

The implementation needs to be registered in your configuration file:

yaml
services:
 -
  class: MyApp\PHPStan\SomeParameterClosureTypeExtension
  tags:
   - phpstan.methodParameterClosureTypeExtension

There's also analogous functionality for:

Parameter Closure This

<div class="text-xs inline-block border border-green-600 text-green-600 bg-green-100 rounded px-1 mb-4">Available in PHPStan 2.1.23</div>

While PHPStan supports @param-closure-this to change the meaning of $this inside closures, sometimes static PHPDocs are not sufficient or don't have the necessary context to describe the closure's $this parameter.

You can create an extension that implements MethodParameterClosureThisExtension:

php
use PhpParser\Node\Expr\MethodCall;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\ParameterReflection;

interface MethodParameterClosureThisExtension
{
 public function isMethodSupported(
  MethodReflection $methodReflection,
  ParameterReflection $parameter,
 ): bool;
 
 public function getClosureThisTypeFromMethodCall(
  MethodReflection $methodReflection,
  MethodCall $methodCall,
  ParameterReflection $parameter,
  Scope $scope,
 ): ?Type;
}

The implementation needs to be registered in your configuration file:

yaml
services:
 -
  class: MyApp\PHPStan\SomeParameterClosureThisExtension
  tags:
   - phpstan.methodParameterClosureThisExtension

There's also analogous functionality for: