You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
> **Execution Order Note:** Native PHP type hints (e.g., `int $id`, `string $username`) are evaluated by PHP's C-engine *before* function execution begins. TypePHP's extended PHPDoc contracts (e.g., `positive-int`, `non-empty-string`) execute at the very start of the function/method body. If a native type hint fails, PHP throws its native `TypeError` before TypePHP's guard rails run.
37
37
38
38
---
39
+
39
40
## PHP 8.0+ Named Arguments
40
41
41
42
TypePHP natively supports PHP 8.0+ Named Arguments. Because parameter contracts are mapped by parameter name rather than argument position index, you can pass named arguments in any order, and TypePHP will accurately validate each parameter:
// Throws: TypeError: deleteUsers(): Argument $ids[2] must be of type positive-int
211
-
```
212
-
213
-
---
214
-
215
194
## Fluent `$this` Identity Returns
216
195
217
196
For fluent builder or service classes annotated with `@return $this`, TypePHP verifies strict object identity (`$result === $this`), preventing accidental instantiation of new instances:
@@ -247,6 +226,96 @@ $builder->cloneSelf();
247
226
248
227
---
249
228
229
+
## Late Static Binding Return Contracts (`@return static`)
230
+
231
+
When a parent class method (static factory method or fluent instance method) is annotated with `@return static`, TypePHP enforces **Late Static Binding** at runtime.
232
+
233
+
It dynamically verifies that the returned object is an instance of the **actual calling class** (`UserEntityFactory`), strictly rejecting parent instances (`BaseEntityFactory`), sibling instances (`AdminEntityFactory`), or generic objects (`stdClass`):
234
+
235
+
```php
236
+
abstract class BaseEntityFactory
237
+
{
238
+
/**
239
+
* @return static
240
+
*/
241
+
public static function create(): static
242
+
{
243
+
return new static();
244
+
}
245
+
246
+
/**
247
+
* @return static
248
+
*/
249
+
public static function createSibling(): object
250
+
{
251
+
return new AdminEntityFactory(); // Invalid: Returns sibling instead of calling class!
252
+
}
253
+
}
254
+
255
+
class UserEntityFactory extends BaseEntityFactory {}
256
+
class AdminEntityFactory extends BaseEntityFactory {}
257
+
258
+
// Valid: Returns UserEntityFactory instance matching the late-static calling class
259
+
$user = UserEntityFactory::create();
260
+
261
+
// Invalid: UserEntityFactory called, but AdminEntityFactory was returned!
262
+
UserEntityFactory::createSibling();
263
+
// Throws: TypeError: UserEntityFactory::createSibling(): Return value must be of type App\UserEntityFactory, App\AdminEntityFactory returned
264
+
```
265
+
266
+
### Late Static Binding with Generics (`static<T>`)
267
+
268
+
Late static binding seamlessly integrates with TypePHP's Reified Generics engine. A static factory can return a specialized generic instance of the late-static-bound calling class:
269
+
270
+
```php
271
+
/**
272
+
* @template T
273
+
*/
274
+
abstract class BaseGenericFactory
275
+
{
276
+
/**
277
+
* @template TValue
278
+
* @param TValue $value
279
+
* @return static<TValue>
280
+
*/
281
+
public static function of(mixed $value): static
282
+
{
283
+
return new static($value);
284
+
}
285
+
}
286
+
287
+
class UserGenericFactory extends BaseGenericFactory {}
288
+
289
+
// 1. Returns UserGenericFactory instance
290
+
// 2. Binds generic template T = Dog in WeakMap memory!
291
+
$factory = UserGenericFactory::of(new Dog());
292
+
```
293
+
294
+
---
295
+
296
+
## Variadic Parameter Contracts
297
+
298
+
When a function or method accepts variadic arguments (`...$items`), TypePHP validates every element passed in the variadic argument list:
You can place your PHPDoc annotations **either above or below** native PHP attributes on properties, methods/functions. TypePHP's AST engine and PHP's Reflection API process both metadata channels independently without any syntax conflicts:
349
+
You can place your PHPDoc annotations **either above or below** native PHP attributes on properties, methods, or functions. TypePHP's AST engine and PHP's Reflection API process both metadata channels independently without any syntax conflicts:
0 commit comments