yii2-extensions / phpstan
PHPStan extension for Yii2
Fund package maintenance!
terabytesoftw
Installs: 71 285
Dependents: 26
Suggesters: 0
Security: 0
Stars: 8
Watchers: 1
Forks: 2
Open Issues: 0
pkg:composer/yii2-extensions/phpstan
Requires
- php: >=8.1
- nikic/php-parser: ^4.1|^5.4.0
- phpstan/phpstan: ^2.1
- yiisoft/yii2: ^2.0.53|^22
Requires (Dev)
- maglnet/composer-require-checker: ^4.7
- phpstan/phpstan-phpunit: ^2.0
- phpstan/phpstan-strict-rules: ^2.0.3
- phpunit/phpunit: ^10.2
- symplify/easy-coding-standard: ^12.1
This package is auto-updated.
Last update: 2025-10-11 11:10:37 UTC
README
PHPStan
Enhanced static analysis for Yii2 applications with PHPStan
Precise type inference, dynamic method resolution, and comprehensive property reflection
Features
Installation
composer require --dev yii2-extensions/phpstan:^0.3
Quick start
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 [ // PHPStan only: used by this extension for behavior property/method type inference 'behaviors' => [ app\models\User::class => [ app\behaviors\SoftDeleteBehavior::class, yii\behaviors\TimestampBehavior::class, ], ], '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
Type inference examples
Active Record
// ✅ 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');
Application components
// ✅ 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 }
Behaviors
// Behaviors are attached via the `phpstan-config.php` behaviors map (PHPStan only) /** * @property string $slug * @property-read int $created_at * * Note: `created_at` is provided by `TimestampBehavior`. */ class SoftDeleteBehavior extends \yii\base\Behavior { public function softDelete(): bool { /* ... */ } } // ✅ Typed based on your configuration $user = new User(); // ✅ Typed as string (inferred from behavior property) $slug = $user->getAttribute('slug'); // ✅ Direct property access is also inferred (behavior property) $slug2 = $user->slug; // ✅ Typed as int (inferred from behavior property) $createdAt = $user->getAttribute('created_at'); // ✅ Typed as bool (method defined in attached behavior) $result = $user->softDelete();
Dependency injection
$container = new Container(); // ✅ Type-safe service resolution $service = $container->get(MyService::class); // MyService $logger = $container->get('logger'); // LoggerInterface (if configured) or mixed
Header collection
$headers = new HeaderCollection(); // ✅ Typed as string|null $host = $headers->get('Host'); // ✅ Typed as array<int, string> $forwardedFor = $headers->get('X-Forwarded-For', ['127.0.0.1'], false); // ✅ Dynamic return type inference with mixed default $default = 'default-value'; $requestId = $headers->get('X-Request-ID', $default, true); // string|null $allRequestIds = $headers->get('X-Request-ID', $default, false); // array<int, string>|null
Service locator
$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
Documentation
For detailed configuration options and advanced usage.