Przejdź do głównej zawartości
PHP Ecosystem
Explore

PHPStan

Ta treść nie jest jeszcze dostępna w Twoim języku.

Enhanced static analysis for Yii2 applications with PHPStan

Precise type inference, dynamic method resolution, and comprehensive property reflection

Feature Overview

Terminal window
composer require --dev yii2-extensions/phpstan:^0.5

Create config/phpstan.php with an analysis-only description of your application:

<?php
declare(strict_types=1);
return [
'params' => ['adminEmail' => 'admin@example.com'],
'components' => [
'db' => ['class' => yii\db\Connection::class],
],
];

Create phpstan.neon in the project root, choosing paths that exist in your application:

includes:
- vendor/yii2-extensions/phpstan/extension.neon
parameters:
level: 5
paths:
- models
yii2:
config_path: config/phpstan.php

Run PHPStan:

Terminal window
vendor/bin/phpstan analyse

The snippets below assume an app\models\Article model with id and title property tags and a published() query scope. The usage guide describes the analysis configuration for the components, params and behaviors shown here.

Yii supplies generic types for findOne(), findAll(), relations and the standard query methods. This extension adds row shapes from model @property tags and precise getAttribute() types:

use app\models\Article;
$article = Article::findOne(1); // Article|null
$articles = Article::findAll(['title' => 'Yii']); // array<Article>
$query = Article::find()->where(['id' => 1]); // ArticleQuery&ActiveQuery<Article>
$published = Article::find()->published()->one(); // Article|null
$rows = Article::find()->asArray()->all(); // array<array{id: int, title: string}>
if ($article !== null) {
$title = $article->getAttribute('title'); // string
}

A custom query without generic PHPDoc, such as one generated by Gii, is bound to the model at the find() call site. Use static or $this scope return types to preserve that binding. Row shapes include inherited property tags; relation and read-only keys are optional and need guards such as ??. See query limitations when a query is reached through a typed parameter or a widened relation getter.

Yii::$app uses phpstan.application_type, which defaults to yii\web\Application. Component classes come from the analysis configuration:

$view = Yii::$app->exampleView; // yii\web\View
$typed = Yii::$app->get('typedView'); // yii\web\View
$untyped = Yii::$app->get('untypedView'); // object
$request = Yii::$app->request; // yii\web\Request

Class names, class-key arrays, object instances and factories with a single class return type can provide precise types. An untyped factory yields object; adding an accurate return type makes the result specific. Core components configured without a class keep the application’s annotated property type.

The built-in user: identityClass mapping also supplies the configured identity class to yii\web\User’s generic parameter. Its identity property remains nullable. See generic components and the separate console application configuration.

Params values become an array shape, including nested arrays and keys containing dots or other punctuation:

$email = Yii::$app->params['adminEmail']; // string
$maxItems = Yii::$app->params['maxItems']; // int
$enabled = Yii::$app->params['nested']['enabled']; // bool

Scalars are widened to their types rather than retained as literal values. The same shape applies to inherited module params, including $this->module->params in a controller. With no configured params, the type stays array.

The analysis-only behaviors map exposes members from attached behavior classes. In the example, TaggedComponent is mapped to TagBehavior; the application must also attach that behavior at runtime:

use app\behaviors\TagBehavior;
use app\components\TaggedComponent;
$component = new TaggedComponent();
$component->attachBehavior('tag', new TagBehavior());
$label = $component->label; // string
$summary = $component->summarize(); // string

Properties and methods are resolved from the behavior’s native members and PHPDoc. See behavior configuration.

Container service definitions and aliases are resolved by their IDs:

$view = Yii::$container->get('view.alias'); // yii\web\View
$shared = Yii::$container->get('sharedView'); // yii\web\View

The example config maps view.alias to view.real and gives sharedView a typed factory. An unresolved definition keeps the result as object. Container factories, invocable objects and aliases have distinct rules; see definition forms.

$headers = new yii\web\HeaderCollection();
$host = $headers->get('Host'); // string|null
$ids = $headers->get('X-Request-ID', [], false); // array<string>
$requestId = $headers->get('X-Request-ID', 'default'); // string

A non-null default removes null from the return type. The $first argument selects a single value or an array.

Logger and target message buffers have tuple types without local stubs or PHPDoc overrides:

foreach ((new yii\log\Logger())->messages as $message) {
$level = $message[1]; // int
$category = $message[2]; // string
$timestamp = $message[3]; // float
$memory = $message[5] ?? null; // int|null
}
$empty = yii\log\Target::filterMessages([]); // array{}

Payload types follow the installed Yii version. Filtering preserves the input key and tuple types while allowing an empty result. See the logger examples.

A service locator resolves configured component IDs, while container-only IDs belong to the container:

$view = Yii::$app->get('exampleView'); // yii\web\View
$optional = Yii::$app->get('exampleView', false); // yii\web\View|null
$unknown = Yii::$app->get('view.alias'); // object; not a configured component ID

Passing false or a non-constant boolean as $throwException makes a resolved component nullable. An object fallback does not guarantee a successful runtime lookup: unknown component IDs can throw. Use Yii::$container->get('view.alias') for the configured container alias.

Practical guides and complete examples for Yii type inference and application analysis.

AI agents: use the repository guides and source for the installed revision. For a documentation deployment with llms.txt, read that index first. When Markdown export is enabled, append index.md to a page URL. For Yii conventions, use the yii2-framework skill from a local framework documentation checkout.

If the hosted sources are unavailable, use the repository guides and locally available skills.

Follow on X Follow on Facebook Join our Subreddit Join on Telegram

License