A type brought in with @phpstan-import-type is a local alias, not a class
in the model's namespace, but it was resolved as one:
@property-read \App\Models\ArrayShape $some_array
Collect the aliases declared with @phpstan-type/@psalm-type or imported
with @phpstan-import-type/@psalm-import-type on the model and its parents,
and return them as written.
Fixes#1773
When the related model uses SoftDeletes, `isRelationNullable()` was
forcing the BelongsTo relation type to nullable even if the relation
explicitly opted into trashed parents via `->withTrashed()`. Combined
with a NOT NULL FK column and DB-level FK constraint, the relation is
effectively non-nullable.
The SoftDeletes branch is now skipped when the relation has removed
the `SoftDeletingScope` and added no constraint on the qualified
`deleted_at` column. `->onlyTrashed()` and `->withoutTrashed()` keep
their nullable annotation because they restrict the parent to a
specific soft-delete state.
Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
The MetaCommand's custom autoloader throws a ReflectionException for any
class not found during meta generation. However, this breaks libraries
that use class_exists() to check for optional dependencies before loading
them (e.g. Doctrine ORM checking for StaticReflectionService removed in
doctrine/persistence v4).
This fix checks the call stack (up to 3 frames) for class_exists(),
interface_exists(), trait_exists(), or enum_exists() calls and returns
gracefully instead of throwing, allowing the existence check to return
false as expected.
Fixes#1750
When using --write/-W with models that have PHP 8 attributes (e.g.
#[ObservedBy(...)]), the generated PHPDoc block was inserted between
the attribute and the class declaration:
#[ObservedBy([ImageObserver::class])]
/**
* @property string $name
*/
final class Image extends Model
This breaks PHPStan/Larastan because the docblock must come before
the attributes. The fix scans backward from the class declaration to
find any preceding PHP 8 attributes and inserts the docblock before
them:
/**
* @property string $name
*/
#[ObservedBy([ImageObserver::class])]
final class Image extends Model
Fixes#1734
When a MorphTo relation's docblock uses a bare intersection type in the
generic parameter (e.g. `MorphTo<BaseModel&CanBeAssigned, $this>`), the
generated property type incorrectly becomes `BaseModel&CanBeAssigned|null`
instead of the correct `(BaseModel&CanBeAssigned)|null`.
This adds `wrapIntersectionType()` which ensures bare intersection types
are wrapped in parentheses before `|null` is appended, producing valid
DNF type syntax. Applied in both `setProperty()` and `applyNullability()`.
- Convert usedMethods from list to hash map for O(1) dedup lookups
- Cache getRelationTypes() and getRelationReturnTypes() per command run
- Reuse SplFileObject instances by filename instead of re-opening per method
- Cache ContextFactory results per declaring class across docblock helpers
Benchmarked with hyperfine (10 runs, 2 warmup): 1.37x faster (~27%).
* Add support for `decimal` column type
Previously `decimal` columns were represented with a cast. This now is no longer the case and instead the column type itself is `decimal`. This change takes that into account.
* The column type may also be `numeric`
* Update tests
* Support `AsCollection::of($map)`, `AsCollection::using($class, $map)`
* test compatibility(`of($map)`,`using($class, $map)` compiled), only laravel `>=12.10`
* fix(pivot): only use unique classes in the pivot union (Fixes#1606)
* composer fix-style
---------
Co-authored-by: laravel-ide-helper <[email protected]>
* feat: support generics eloquent builder
* fix: required laravel version
* fix: ci execution is only for Laravel-11
* docs: add CHANGELOG
* docs: update supported Laravel versions and adjust output examples
* Add `\\static` as check
For some reason, the `static` keyword as a return type, does not return `isBuiltin()` === true, so a `\\` is added. We need to manually add it to the built in check.
* Update ModelsCommand.php
* Add tests
* Add CHANGELOG.md entry
---------
Co-authored-by: Markus Podar <[email protected]>
Co-authored-by: Barry vd. Heuvel <[email protected]>