PHPStan extension for Yii2

Package info

github.com/yii2-extensions/phpstan

pkg:composer/yii2-extensions/phpstan

Statistics

Installs: 162โ€‰654

Dependents: 36

Suggesters: 0

Stars: 19

Open Issues: 0

0.4.1 2026-04-05 16:01 UTC

Requires

Suggests

None

Provides

None

Conflicts

None

Replaces

None

BSD-3-Clause 73d24f71bd1e19e3836f64900019025edae9d8bb

yii2PHPStan

This package is auto-updated.

Last update: 2026-06-24 12:53:10 UTC


README

๐Ÿ‘ Yii Framework

PHPStan


๐Ÿ‘ PHPUnit
๐Ÿ‘ PHPStan
๐Ÿ‘ Security

Enhanced static analysis for Yii2 applications with PHPStan
Precise type inference, dynamic method resolution, and comprehensive property reflection

Features

๐Ÿ‘ Feature Overview

Installation

composer require --dev yii2-extensions/phpstan:^0.4

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 [
 // Application params: enables precise type inference for Yii::$app->params
 'params' => [
 'turnstile.siteKey' => '',
 'adminEmail' => 'admin@example.com',
 'maxItems' => 100,
 ],
 // 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
}

Application params

// Types are inferred from the values in your phpstan-config.php 'params' key

// โœ… Typed as array{'turnstile.siteKey': string, adminEmail: string, maxItems: int}
$params = Yii::$app->params;

// โœ… Typed as string
$email = Yii::$app->params['adminEmail'];

// โœ… Typed as int
$maxItems = Yii::$app->params['maxItems'];

// โœ… Nested arrays are also supported
// 'nested' => ['db' => ['host' => 'localhost', 'port' => 3306]]
$host = Yii::$app->params['nested']['db']['host']; // string

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.

Package information

๐Ÿ‘ PHP
๐Ÿ‘ Yii 2.0.x
๐Ÿ‘ Yii 22.0.x
๐Ÿ‘ Latest Stable Version
๐Ÿ‘ Total Downloads

Project status

๐Ÿ‘ Codecov
๐Ÿ‘ PHPStan Level Max
๐Ÿ‘ Quality
๐Ÿ‘ StyleCI

Our social networks

๐Ÿ‘ Follow on X
๐Ÿ‘ Follow on Facebook
๐Ÿ‘ Join our Subreddit
๐Ÿ‘ Join on Telegram

License

๐Ÿ‘ License