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
Since #1674 (commit 09623f2), the generated IDE helper file adds an
`extends` declaration for Macroable classes to expose inherited methods.
However, the check to skip facades only excluded classes in the
`\Illuminate\Support\Facades` namespace, so third-party facades (e.g.
`Spatie\Menu\Laravel\Facades\Menu`) would incorrectly extend the
facade root's parent class.
This caused the generated stub to conflict with the real facade class:
namespace Spatie\Menu\Laravel\Facades {
class Menu extends \Spatie\Menu\Menu { // wrong!
The fix checks whether the extends class IS a Facade subclass (using
`is_subclass_of`) rather than comparing namespace strings. This
correctly excludes ALL facade classes (both Laravel and third-party)
while still allowing non-facade Macroable classes to extend their
parent.
Fixes#1724
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
The 'Support for camel cased models' comment block used 5-space
indentation for the pipe characters instead of the standard 4 spaces
used by all other comment blocks in the config file.
Fixes#1761
* Bump dependencies for Laravel 13
* Update GitHub Actions for Laravel 13
* Update workflow to remove cron schedule
Removed cron schedule and adjusted pull request branches.
* Fix syntax, modify Laravel version in run-tests.yml
Updated Laravel version from '13.0' to '13.x' in CI configuration.
* Update test-ci command in composer.json
* Fix test-ci command in composer.json
---------
Co-authored-by: Barry vd. Heuvel <[email protected]>
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%).
* Skip calling fake() on facades that require parameters (fix Socialite error)
The ide-helper attempted to invoke Facade::fake() unconditionally, which
breaks when a facade (such as Laravel Socialite) requires a mandatory
parameter in its fake() method signature. This resulted in an
ArgumentCountError during `php artisan ide-helper:generate`.
This patch adds a ReflectionMethod check and skips calling fake() when
required parameters are present, ensuring compatibility with Socialite
and preserving expected behavior for facades that support parameterless
faking.
* Update Alias.php
---------
Co-authored-by: Barry vd. Heuvel <[email protected]>
* 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
- Fixed 'seperate' to 'separate' in README.md (2 occurrences)
- Fixed 'columname' to 'columnname' in README.md (2 occurrences)
- Fixed 'Wether' to 'Whether' in src/Method.php PHPDoc comments (2 occurrences)
* Support `AsCollection::of($map)`, `AsCollection::using($class, $map)`
* test compatibility(`of($map)`,`using($class, $map)` compiled), only laravel `>=12.10`