|
26 | 26 | </a>
|
27 | 27 | </p>
|
28 | 28 |
|
29 |
| -## Installation |
30 |
| - |
31 |
| -The preferred way to install this extension is through [composer](https://getcomposer.org/download/). |
| 29 | +A comprehensive PHPStan extension that provides enhanced static analysis for Yii2 applications with precise type |
| 30 | +inference, dynamic method resolution, and comprehensive property reflection. |
32 | 31 |
|
33 |
| -Either run |
| 32 | +## Installation |
34 | 33 |
|
35 |
| -```shell |
36 |
| -composer require --dev --prefer-dist yii2-extensions/phpstan:^0.2 |
| 34 | +```bash |
| 35 | +composer require --dev yii2-extensions/phpstan |
37 | 36 | ```
|
38 | 37 |
|
39 |
| -or add |
| 38 | +## Features |
40 | 39 |
|
41 |
| -```json |
42 |
| -"yii2-extensions/phpstan": "^0.2" |
43 |
| -``` |
| 40 | +✅ **ActiveRecord & ActiveQuery Analysis** |
| 41 | +- Array/object result type inference based on `asArray()` usage. |
| 42 | +- Dynamic return type inference for `find()`, `findOne()`, `findAll()` methods. |
| 43 | +- Generic type support for `ActiveQuery<Model>` with proper chaining. |
| 44 | +- Relation methods (`hasOne()`, `hasMany()`) with accurate return types. |
44 | 45 |
|
45 |
| -## Usage |
| 46 | +✅ **Application Component Resolution** |
| 47 | +- Automatic type inference for `Yii::$app->component` access. |
| 48 | +- Behavior property and method reflection. |
| 49 | +- Support for custom component configurations. |
| 50 | +- User component with `identity`, `id`, `isGuest` property types. |
46 | 51 |
|
47 |
| -This extension provides enhanced static analysis for `Yii2` applications by adding: |
| 52 | +✅ **Dependency Injection Container** |
| 53 | +- Service map integration for custom services. |
| 54 | +- Support for closures, singletons, and nested definitions. |
| 55 | +- Type-safe `Container::get()` method resolution. |
48 | 56 |
|
49 |
| -- **Container service resolution** with proper type inference. |
50 |
| -- **Dynamic method return types** for `ActiveRecord` and `ActiveQuery`. |
51 |
| -- **Header collection dynamic methods** support. |
52 |
| -- **Property reflection extensions** for `Application`, `Request`, `Response`, and `User` components. |
53 |
| -- **Service map integration** for dependency injection analysis. |
| 57 | +✅ **Framework Integration** |
| 58 | +- Header collection dynamic method types. |
| 59 | +- Stub files for different application types (web, console, base). |
| 60 | +- Support for Yii2 constants (`YII_DEBUG`, `YII_ENV_*`). |
54 | 61 |
|
55 |
| -### Basic Configuration |
| 62 | +## Quick Start |
56 | 63 |
|
57 |
| -To use this extension, you need to add the following configuration to your `phpstan.neon` file: |
| 64 | +Create a `phpstan.neon` file in your project root. |
58 | 65 |
|
59 | 66 | ```neon
|
60 | 67 | includes:
|
61 | 68 | - vendor/yii2-extensions/phpstan/extension.neon
|
62 | 69 |
|
63 | 70 | parameters:
|
64 |
| - bootstrapFiles: |
65 |
| - - tests/bootstrap.php |
66 |
| -
|
67 | 71 | level: 5
|
68 |
| -
|
69 | 72 | paths:
|
70 | 73 | - src
|
71 |
| -
|
72 |
| - # Exclude paths from analysis |
73 |
| - excludePaths: |
74 |
| - - c3.php |
75 |
| - - requirements.php |
76 |
| - - config |
77 |
| - - tests |
78 |
| - - vendor |
79 |
| -
|
| 74 | + - controllers |
| 75 | + - models |
| 76 | + |
80 | 77 | yii2:
|
81 |
| - # Path to your `Yii2` configuration file (optional) |
82 |
| - # If not provided or empty, will work without explicit configuration |
83 |
| - config_path: %currentWorkingDirectory%/config/test.php |
| 78 | + config_path: config/test.php |
84 | 79 | ```
|
85 | 80 |
|
86 |
| -### Dynamic Constants Configuration |
87 |
| - |
88 |
| -The extension automatically recognizes common `Yii2` dynamic constants: |
| 81 | +Create a PHPStan-specific config file (`config/test.php`). |
89 | 82 |
|
90 |
| -- `YII_DEBUG` |
91 |
| -- `YII_ENV` |
92 |
| -- `YII_ENV_DEV` |
93 |
| -- `YII_ENV_PROD` |
94 |
| -- `YII_ENV_TEST` |
95 |
| - |
96 |
| -If you need to add additional dynamic constants, you can extend the configuration: |
97 |
| - |
98 |
| -```neon |
99 |
| -includes: |
100 |
| - - vendor/yii2-extensions/phpstan/extension.neon |
| 83 | +```php |
| 84 | +<?php |
| 85 | +return [ |
| 86 | + 'components' => [ |
| 87 | + 'db' => [ |
| 88 | + 'class' => yii\db\Connection::class, |
| 89 | + 'dsn' => 'sqlite::memory:', |
| 90 | + ], |
| 91 | + 'user' => [ |
| 92 | + 'class' => yii\web\User::class, |
| 93 | + 'identityClass' => app\models\User::class, |
| 94 | + ], |
| 95 | + // Add your custom components here |
| 96 | + ], |
| 97 | +]; |
| 98 | +``` |
101 | 99 |
|
102 |
| -parameters: |
103 |
| - # Your existing dynamic constants will be merged with the extension's defaults |
104 |
| - dynamicConstantNames: |
105 |
| - - YII_DEBUG # Already included by the extension |
106 |
| - - YII_ENV # Already included by the extension |
107 |
| - - YII_ENV_DEV # Already included by the extension |
108 |
| - - YII_ENV_PROD # Already included by the extension |
109 |
| - - YII_ENV_TEST # Already included by the extension |
110 |
| - - MY_CUSTOM_CONSTANT |
111 |
| - - ANOTHER_CONSTANT |
| 100 | +Run `PHPStan`. |
112 | 101 |
|
113 |
| - yii2: |
114 |
| - config_path: %currentWorkingDirectory%/config/test.php |
| 102 | +```bash |
| 103 | +vendor/bin/phpstan analyse |
115 | 104 | ```
|
116 | 105 |
|
117 |
| -**Note:** When you define `dynamicConstantNames` in your configuration, it **replaces** the extension's default |
118 |
| -constants. |
119 |
| -To maintain the `Yii2` constants recognition, you must include them explicitly along with your custom constants, as |
120 |
| -shown above. |
| 106 | +## Type Inference Examples |
121 | 107 |
|
122 |
| -### Strict Configuration |
| 108 | +### ActiveRecord |
123 | 109 |
|
124 |
| -```neon |
125 |
| -includes: |
126 |
| - - phar://phpstan.phar/conf/bleedingEdge.neon |
127 |
| - - vendor/phpstan/phpstan-strict-rules/rules.neon |
128 |
| - - vendor/yii2-extensions/phpstan/extension.neon |
| 110 | +```php |
| 111 | +// ✅ Properly typed as User|null |
| 112 | +$user = User::findOne(1); |
129 | 113 |
|
130 |
| -parameters: |
131 |
| - bootstrapFiles: |
132 |
| - - tests/bootstrap.php |
133 |
| -
|
134 |
| - # Complete dynamic constants list (extension defaults + custom) |
135 |
| - dynamicConstantNames: |
136 |
| - - YII_DEBUG |
137 |
| - - YII_ENV |
138 |
| - - YII_ENV_DEV |
139 |
| - - YII_ENV_PROD |
140 |
| - - YII_ENV_TEST |
141 |
| - - APP_VERSION |
142 |
| - - MAINTENANCE_MODE |
143 |
| -
|
144 |
| - level: 8 |
145 |
| - |
146 |
| - paths: |
147 |
| - - src |
148 |
| - - controllers |
149 |
| - - models |
150 |
| - - widgets |
| 114 | +// ✅ Properly typed as User[] |
| 115 | +$users = User::findAll(['status' => 'active']); |
151 | 116 |
|
152 |
| - excludePaths: |
153 |
| - - src/legacy |
154 |
| - - tests/_support |
155 |
| - - vendor |
| 117 | +// ✅ Generic ActiveQuery<User> with method chaining |
| 118 | +$query = User::find()->where(['active' => 1])->orderBy('name'); |
156 | 119 |
|
157 |
| - yii2: |
158 |
| - config_path: %currentWorkingDirectory%/config/web.php |
159 |
| -
|
160 |
| - # Enable strict advanced checks |
161 |
| - checkImplicitMixed: true |
162 |
| - checkBenevolentUnionTypes: true |
163 |
| - checkUninitializedProperties: true |
164 |
| - checkMissingCallableSignature: true |
165 |
| - checkTooWideReturnTypesInProtectedAndPublicMethods: true |
166 |
| - reportAnyTypeWideningInVarTag: true |
167 |
| - reportPossiblyNonexistentConstantArrayOffset: true |
168 |
| - reportPossiblyNonexistentGeneralArrayOffset: true |
| 120 | +// ✅ Array results properly typed as array{id: int, name: string}[] |
| 121 | +$userData = User::find()->asArray()->all(); |
169 | 122 | ```
|
170 | 123 |
|
171 |
| -### PHPstan extension installer |
| 124 | +### Application Components |
172 | 125 |
|
173 |
| -You can use the `phpstan-extension-installer` to automatically install this extension. |
174 |
| - |
175 |
| -To do this, you need to add the following configuration to your `composer.json` file: |
176 |
| - |
177 |
| -```shell |
178 |
| -composer require --dev phpstan/extension-installer |
179 |
| -``` |
180 |
| - |
181 |
| -or, add the following to your `composer.json`: |
182 |
| - |
183 |
| -```json |
184 |
| -{ |
185 |
| - "require-dev": { |
186 |
| - "phpstan/extension-installer": "^1.4" |
187 |
| - }, |
188 |
| - "config": { |
189 |
| - "allow-plugins": { |
190 |
| - "phpstan/extension-installer": true |
191 |
| - } |
192 |
| - }, |
| 126 | +```php |
| 127 | +// ✅ Properly typed based on your configuration |
| 128 | +$mailer = Yii::$app->mailer; // MailerInterface |
| 129 | +$db = Yii::$app->db; // Connection |
| 130 | +$user = Yii::$app->user; // User |
| 131 | + |
| 132 | +// ✅ User identity with proper type inference |
| 133 | +if (Yii::$app->user->isGuest === false) { |
| 134 | + $userId = Yii::$app->user->id; // int|string|null |
| 135 | + $identity = Yii::$app->user->identity; // YourUserClass |
193 | 136 | }
|
194 | 137 | ```
|
195 | 138 |
|
196 |
| -### Config `yii2` application for PHPStan |
197 |
| - |
198 |
| -To configure the `yii2` application, you can use the `yii2` section in your `phpstan.neon` file: |
199 |
| - |
200 |
| -```neon |
201 |
| -parameters: |
202 |
| - yii2: |
203 |
| - # Path to your `Yii2` configuration file |
204 |
| - config_path: %currentWorkingDirectory%/config/test.php |
205 |
| -``` |
206 |
| - |
207 |
| -`config/test.php` file should return an array with the application configuration, similar to the following: |
| 139 | +### Dependency Injection |
208 | 140 |
|
209 | 141 | ```php
|
210 |
| -<?php |
211 |
| - |
212 |
| -declare(strict_types=1); |
213 |
| - |
214 |
| -use yii2\extensions\localeurls\UrlLanguageManager; |
| 142 | +$container = new Container(); |
215 | 143 |
|
216 |
| -return [ |
217 |
| - 'components' => [ |
218 |
| - // custom component |
219 |
| - 'helper' => [ |
220 |
| - 'class' => \yii2\extensions\helper\Helper::class, |
221 |
| - ], |
222 |
| - // your component extended |
223 |
| - 'urlManager' => [ |
224 |
| - 'class' => UrlLanguageManager::class, |
225 |
| - ], |
226 |
| - ], |
227 |
| -]; |
| 144 | +// ✅ Type-safe service resolution |
| 145 | +$service = $container->get(MyService::class); // MyService |
| 146 | +$logger = $container->get('logger'); // LoggerInterface (if configured) |
228 | 147 | ```
|
229 | 148 |
|
| 149 | +## Documentation |
| 150 | + |
| 151 | +For detailed configuration options and advanced usage. |
230 | 152 |
|
| 153 | +- 📚 [Installation Guide](docs/installation.md) |
| 154 | +- ⚙️ [Configuration Reference](docs/configuration.md) |
| 155 | +- 💡 [Usage Examples](docs/examples.md) |
231 | 156 |
|
232 | 157 | ## Quality code
|
233 | 158 |
|
|
0 commit comments