Menu

Class Reflection Extensions

Classes in PHP can expose “magic” properties and methods decided in run-time using class methods like __get, __set, and __call. Because PHPStan is all about static analysis (testing code for errors without running it), it has to know about those properties and methods beforehand.

When PHPStan stumbles upon a property or a method that is unknown to built-in class reflection, it iterates over all registered class reflection extensions until it finds one that defines the property or method.

Properties class reflection extensions #

To describe magic properties from __get and __set methods, an extension must implement the following interface:

namespace PHPStan\Reflection;

interface PropertiesClassReflectionExtension
{

public function hasProperty(ClassReflection $classReflection, string $propertyName): bool;

public function getProperty(ClassReflection $classReflection, string $propertyName): PropertyReflection;

}

Most likely you will also have to implement a new class implementing the PropertyReflection interface:

namespace PHPStan\Reflection;

use PHPStan\TrinaryLogic;
use PHPStan\Type\Type;

interface PropertyReflection
{

public function getDeclaringClass(): ClassReflection;

public function isStatic(): bool;

public function isPrivate(): bool;

public function isPublic(): bool;

public function getDocComment(): ?string;

public function getReadableType(): Type;

public function getWritableType(): Type;

public function canChangeTypeAfterAssignment(): bool;

public function isReadable(): bool;

public function isWritable(): bool;

public function isDeprecated(): TrinaryLogic;

public function getDeprecatedDescription(): ?string;

public function isInternal(): TrinaryLogic;

}

This is how you register the extension in the configuration file:

services:
-
class: App\PHPStan\PropertiesFromAnnotationsClassReflectionExtension
tags:
- phpstan.broker.propertiesClassReflectionExtension

Methods class reflection extensions #

To describe magic methods from the __call method, an extension must implement the MethodsClassReflectionExtension interface:

namespace PHPStan\Reflection;

interface MethodsClassReflectionExtension
{

public function hasMethod(ClassReflection $classReflection, string $methodName): bool;

public function getMethod(ClassReflection $classReflection, string $methodName): MethodReflection;

}

Most likely you will also have to implement a new class implementing the MethodReflection interface:

namespace PHPStan\Reflection;

use PHPStan\TrinaryLogic;
use PHPStan\Type\Type;

interface MethodReflection
{

public function getDeclaringClass(): ClassReflection;

public function isStatic(): bool;

public function isPrivate(): bool;

public function isPublic(): bool;

public function getDocComment(): ?string;

public function getName(): string;

public function getPrototype(): ClassMemberReflection;

/**
* @return \PHPStan\Reflection\ParametersAcceptor[]
*/

public function getVariants(): array;

public function isDeprecated(): TrinaryLogic;

public function getDeprecatedDescription(): ?string;

public function isFinal(): TrinaryLogic;

public function isInternal(): TrinaryLogic;

public function getThrowType(): ?Type;

public function hasSideEffects(): TrinaryLogic;

}

This is how you register the extension in the configuration file:

services:
-
class: App\PHPStan\EnumMethodsClassReflectionExtension
tags:
- phpstan.broker.methodsClassReflectionExtension

Edit this page on GitHub

© 2016–2020 Petra Mirtesová