A comprehensive PHPStan extension that provides enhanced static analysis for Yii2 applications with precise type inference, dynamic method resolution, and comprehensive property reflection.
✅ ActiveRecord & ActiveQuery Analysis
- Array/object result type inference based on
asArray()
usage. - Dynamic return type inference for
find()
,findOne()
,findAll()
methods. - Generic type support for
ActiveQuery<Model>
with proper chaining. - Hierarchical type resolution: model properties take precedence over behavior properties.
- Precise type inference for
getAttribute()
method calls based on PHPDoc annotations. - Property type resolution from both model classes and attached behaviors.
- Relation methods (
hasOne()
,hasMany()
) with accurate return types. - Support for behavior property definitions through ServiceMap integration.
✅ Application Component Resolution
- Automatic type inference for
Yii::$app->component
access. - Behavior property and method reflection.
- Generic component support with configurable type parameters.
- Non-destructive generic configuration - extend without overriding defaults.
- Support for custom component configurations.
- User component with
identity
,id
,isGuest
property types.
✅ Dependency Injection Container
- Service map integration for custom services.
- Support for closures, singletons, and nested definitions.
- Type-safe
Container::get()
method resolution.
✅ Framework Integration
- Header collection dynamic method types.
- Stub files for different application types (web, console, base).
- Support for Yii2 constants (
YII_DEBUG
,YII_ENV_*
).
✅ Service Locator Component Resolution
- Automatic fallback to mixed type for unknown component identifiers.
- Dynamic return type inference for
ServiceLocator::get()
calls. - Priority-based resolution: ServiceMap components > ServiceMap services > Real classes > Mixed type.
- Support for all Service Locator subclasses (Application, Module, custom classes).
- Type inference with string variables and class name constants.
composer require --dev yii2-extensions/phpstan
Create a phpstan.neon
file in your project root.
includes:
- vendor/yii2-extensions/phpstan/extension.neon
parameters:
level: 5
paths:
- src
- controllers
- models
tmpDir: %currentWorkingDirectory%/runtime
yii2:
config_path: config/phpstan-config.php
component_generics:
user: identityClass # Built-in (already configured)
repository: modelClass # Custom generic component
Create a PHPStan-specific config file (config/phpstan-config.php
).
<?php
declare(strict_types=1);
return [
'components' => [
'db' => [
'class' => yii\db\Connection::class,
'dsn' => 'sqlite::memory:',
],
'user' => [
'class' => yii\web\User::class,
'identityClass' => app\models\User::class,
],
// Add your custom components here
],
];
Run PHPStan
.
vendor/bin/phpstan analyse
// ✅ Typed as User|null
$user = User::findOne(1);
// ✅ Typed as User[]
$users = User::findAll(['status' => 'active']);
// ✅ Generic ActiveQuery<User> with method chaining
$query = User::find()->where(['active' => 1])->orderBy('name');
// ✅ Array results typed as array{id: int, name: string}[]
$userData = User::find()->asArray()->all();
// ✅ Typed based on model property annotations string
$userName = $user->getAttribute('name');
// ✅ Behavior property resolution string
$slug = $user->getAttribute('slug');
// ✅ Typed based on your configuration
$mailer = Yii::$app->mailer; // MailerInterface
$db = Yii::$app->db; // Connection
$user = Yii::$app->user; // User
// ✅ User identity with proper type inference
if (Yii::$app->user->isGuest === false) {
$userId = Yii::$app->user->id; // int|string|null
$identity = Yii::$app->user->identity; // YourUserClass
}
$container = new Container();
// ✅ Type-safe service resolution
$service = $container->get(MyService::class); // MyService
$logger = $container->get('logger'); // LoggerInterface (if configured) or mixed
$serviceLocator = new ServiceLocator();
// ✅ Get component with type inference with class
$mailer = $serviceLocator->get(Mailer::class); // MailerInterface
// ✅ Get component with string identifier and without configuration in ServiceMap
$mailer = $serviceLocator->get('mailer'); // MailerInterface (if configured) or mixed
// ✅ User component with proper type inference in Action or Controller
$user = $this->controller->module->get('user'); // UserInterface
For detailed configuration options and advanced usage.
This package is a fork of proget-hq/phpstan-yii2 with some corrections.