|
2 | 2 | <a href="https://github.com/yii2-extensions/phpstan" target="_blank"> |
3 | 3 | <img src="https://www.yiiframework.com/image/yii_logo_light.svg" height="100px;"> |
4 | 4 | </a> |
5 | | - <h1 align="center">Extension for PHPStan.</h1> |
| 5 | + <h1 align="center">Extension for PHPStan</h1> |
6 | 6 | </p> |
7 | 7 |
|
8 | 8 | <p align="center"> |
|
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