Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Plugin Laravel Laravel Package

psalm/plugin-laravel

Laravel Psalm plugin for deep static analysis plus taint-based security scanning. Detects SQL injection, XSS, SSRF, shell injection, path traversal, and open redirects by tracking user input through Laravel code without running it.

View on GitHub
Deep Wiki
Context7
v4.15.1

This release improves Eloquent pluck() and builder type narrowing, plus primary-key and factory binding inference.

Features

  • Narrow single-argument pluck()->all() to list<TValue> (#1299)
 Task::all()->pluck('id')->all();
-// array<int, int> -- rejected by a list<int> return type
+// list<int> -- pluck() always reindexes sequentially
  • Fix pluck() and aggregate narrowing on custom subclasses, raw aliases, and schema-typed columns (#1288)
 /** [@extends](https://github.com/extends) Builder<Task> */
 class TaskBuilder extends Builder {}

 $tasks->pluck('title');
-// Collection<array-key, mixed> -- LHS fallback only checked generic builders
+// Collection<int, string> -- resolved via [@extends](https://github.com/extends) Builder<Task>
  • Auto-bind Factory<TModel> on bare factory subclasses (#1280)
 class TaskFactory extends Factory {}

 (new TaskFactory())->create();
-// Model -- TModel collapses to base Model with no [@extends](https://github.com/extends) Factory<Task> binding
+// Task -- model resolved via Factory::modelName() at warm-up
  • Narrow Model::getKey() to the model's known primary-key type (#1279)
 class UuidModel extends Model { use HasUuids; }

 $model->getKey();
-// int|string -- always the stub's fallback
+// string -- narrowed from the model's known primary-key type

Fixes

  • Fix custom builder method forwarding on relations (#1267)
 // Order has a custom builder with `firstByMake(): ?self`
 $vehicle->orders()->firstByMake('Toyota');
-// mixed -- custom builder-only methods weren't resolved through the relation
+// ?Order -- forwarded through the relation via Psalm storage

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.15.0...v4.15.1

v3.15.1

This release improves Eloquent pluck() and builder type narrowing, plus primary-key and factory binding inference.

Features

  • Narrow single-argument pluck()->all() to list<TValue> (#1299)
 Task::all()->pluck('id')->all();
-// array<int, int> -- rejected by a list<int> return type
+// list<int> -- pluck() always reindexes sequentially
  • Fix pluck() and aggregate narrowing on custom subclasses, raw aliases, and schema-typed columns (#1288)
 /** [@extends](https://github.com/extends) Builder<Task> */
 class TaskBuilder extends Builder {}

 $tasks->pluck('title');
-// Collection<array-key, mixed> -- LHS fallback only checked generic builders
+// Collection<int, string> -- resolved via [@extends](https://github.com/extends) Builder<Task>
  • Auto-bind Factory<TModel> on bare factory subclasses (#1280)
 class TaskFactory extends Factory {}

 (new TaskFactory())->create();
-// Model -- TModel collapses to base Model with no [@extends](https://github.com/extends) Factory<Task> binding
+// Task -- model resolved via Factory::modelName() at warm-up
  • Narrow Model::getKey() to the model's known primary-key type (#1279)
 class UuidModel extends Model { use HasUuids; }

 $model->getKey();
-// int|string -- always the stub's fallback
+// string -- narrowed from the model's known primary-key type

Fixes

  • Fix custom builder method forwarding on relations (#1267)
 // Order has a custom builder with `firstByMake(): ?self`
 $vehicle->orders()->firstByMake('Toyota');
-// mixed -- custom builder-only methods weren't resolved through the relation
+// ?Order -- forwarded through the relation via Psalm storage

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.15.0...v3.15.1

v3.15.0

What's Changed

v3.15.0 ships the biggest architectural change in the plugin's history: ModelMetadataRegistry, a single per-model metadata store that replaces the ad-hoc reflection and private caches every Eloquent handler used to maintain on its own. This release builds three new model-correctness diagnostics on top of it, validating attributes and relationships on your models, plus a more precise serialization inference — and it's the foundation a lot more diagnostics are planned to build on next.

Upgrade impact

  • UnknownModelAttribute and UndefinedModelRelation report at info by default. Opt into error with <experimental value="true" />.
  • UnresolvableAppendedModelAttribute reports at error by default: a $appends entry with no matching accessor or cast now fails analysis. Downgrade it with a standard issueHandlers entry if that doesn't fit your codebase yet.
  • attributesToArray() / toArray() now infer a precise array shape. Always active, no config needed.

Features

  • ⭐️ Add ModelMetadataRegistry, a per-model metadata store warmed once during AfterCodebasePopulated and shared read-only across every Eloquent handler (#1081, #1201)
  • ⭐️ Add the experimental config flag to promote experimental diagnostics to error (#1248)
  • ⭐️ Add UnknownModelAttribute: flags a create()/fill()/update() key with no backing column, cast, accessor, $appends entry, or [@property](https://github.com/property) (#1167)
 Model::create(['nmae' => 'value']);
-// silently drops the typo, sets nothing
+// UnknownModelAttribute: 'nmae' matches no column, cast, accessor, $appends entry, or [@property](https://github.com/property)
  • ⭐️ Add UnresolvableAppendedModelAttribute: flags a $appends entry with no accessor or cast to actually produce it (#1169)
  • ⭐️ Add UndefinedModelRelation: validates relation names passed to with()/load()/has()/whereHas() against the resolved model (#1181)
 Customer::with('vehicles.typoOnVehicle');
-// no warning, silently ignored at runtime
+// UndefinedModelRelation: Relation 'typoOnVehicle' is not defined on App\Models\Vehicle
  • Infer a precise array shape for attributesToArray()/toArray(), honoring casts, hidden, and appended attributes (#1168, #1184)

Fixes

  • Handle keyless models with nullable primary-key metadata (#1264)
  • Exclude migration files from UnknownModelAttribute (#1265)
  • Stop RelationResolver from autoloading related models, fixing an analysis crash (#1272)

Internal changes

  • Reset stateful handlers between plugin invocations (#1250)
  • Make model metadata warm-up section-isolated, preserving partial metadata after a failure (#1268)
  • Allow psalm-delta on fork PRs with a restore-only cache guard (#1269)

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.14.1592...v3.15.0

v4.15.0

What's Changed

v4.15.0 ships the 2nd biggest architectural change in the plugin's history: ModelMetadataRegistry, a single per-model metadata store that replaces the ad-hoc reflection and private caches every Eloquent handler used to maintain on its own. This release builds three new model-correctness diagnostics on top of it, validating attributes and relationships on your models, plus a more precise serialization inference — and it's the foundation a lot more diagnostics are planned to build on next.

Upgrade impact

  • new UnknownModelAttribute and UndefinedModelRelation report at info by default. Opt into error with <experimental value="true" />.
  • new UnresolvableAppendedModelAttribute reports at error by default: a $appends entry with no matching accessor or cast now fails analysis. Downgrade it with a standard issueHandlers entry if that doesn't fit your codebase yet.
  • attributesToArray() / toArray() now infer a precise array shape. Always active, no config needed.

Features

  • ⭐️ Add ModelMetadataRegistry, a per-model metadata store warmed once during AfterCodebasePopulated and shared read-only across every Eloquent handler (#1081, #1201)
  • ⭐️ Add the experimental psalm.xml config flag to promote experimental features for early adopters (#1248)
  • Add UnknownModelAttribute: flags a create()/fill()/update() key with no backing column, cast, accessor, $appends entry, or [@property](https://github.com/property) (#1167)
 Model::create(['nmae' => 'value']);
-// silently drops the typo, sets nothing
+// UnknownModelAttribute: 'nmae' matches no column, cast, accessor, $appends entry, or [@property](https://github.com/property)
  • ⭐️ Add UnresolvableAppendedModelAttribute: flags a $appends entry with no accessor or cast to actually produce it (#1169)
  • ⭐️ Add UndefinedModelRelation: validates relation names passed to with()/load()/has()/whereHas() against the resolved model (#1181)
 Customer::with('vehicles.typoOnVehicle');
-// no warning, silently ignored at runtime
+// UndefinedModelRelation: Relation 'typoOnVehicle' is not defined on App\Models\Vehicle
  • Infer a precise array shape for attributesToArray()/toArray(), honoring casts, hidden, and appended attributes (#1168, #1184)

Fixes

  • Fix whereDate two-argument overload (#1247)

Internal changes

  • Reset stateful handlers between plugin invocations (#1250)
  • Allow psalm-delta on fork PRs with a restore-only cache guard (#1269)

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.14.12...v4.15.0

v3.14.1592

3.14159265... close enough. Here's your π release, the last one, before a big v3.15

Fixes

  • Fix Eloquent\Builder::whereDate() rejecting DateTimeInterface values (Carbon, DateTimeImmutable) in the two-argument form (#1247)
 Post::query()->whereDate('created_at', CarbonImmutable::now());
-// ImplicitToStringCast (before): Argument 2 expects string but Carbon provided
+// now resolves: whereDate() accepts DateTimeInterface in two-arg form

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.14.12...v3.14.1592

v3.14.12

Narrow several producer and validation return types to their concrete implementations, plus fixes for Cache::driver()->flexible() and monorepo init scanning.

Features

  • Narrow Password::broker(), view()/trans(), and query builder pagination results to their concrete Laravel implementation (#1240)
 Password::broker()->createToken($user);
-// UndefinedInterfaceMethod (before): createToken() only exists on the concrete broker
+// now resolves: typed as Auth\Passwords\PasswordBroker

 view('welcome')->fragment('x');
-// UndefinedInterfaceMethod (before): fragment() only exists on Illuminate\View\View
+// now resolves: typed as View\View
  • Narrow validated integer()/boolean() accessors and rule-bound integer fields from validation rules (#1239, #1237)

Fixes

  • Fix UndefinedInterfaceMethod false positive on Cache::driver()->flexible() (#1233)
  • Fix empty <projectFiles> in psalm-laravel init on Composer monorepos (#1235)

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.14.11...v3.14.12

v4.14.12

Narrow several producer and validation return types to their concrete implementations, plus fixes for Cache::driver()->flexible() and monorepo init scanning.

Features

  • Narrow Password::broker(), view()/trans(), and query builder pagination results to their concrete Laravel implementation (#1240)
 Password::broker()->createToken($user);
-// UndefinedInterfaceMethod (before): createToken() only exists on the concrete broker
+// now resolves: typed as Auth\Passwords\PasswordBroker

 view('welcome')->fragment('x');
-// UndefinedInterfaceMethod (before): fragment() only exists on Illuminate\View\View
+// now resolves: typed as View\View
  • Narrow validated integer()/boolean() accessors and rule-bound integer fields from validation rules (#1239, #1237)

Fixes

  • Fix UndefinedInterfaceMethod false positive on Cache::driver()->flexible() (#1233)
  • Fix empty <projectFiles> in psalm-laravel init on Composer monorepos (#1235)

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.14.11...v4.14.12

v3.14.11

Collection type inference for arbitrary inputs, and partial Laravel boots now surface instead of failing silently, plus three false-positive fixes around query builders and monorepo init already shipped on the 4.x line.

This release bumps min supported Laravel minor versions:

  • ^12.4 to ^12.14
  • ^13.0 to ^13.3

Features

  • Infer collect(), Collection::make(), and LazyCollection::make() return types for arbitrary inputs, not just arrays (#1225)
 collect('hello');
-// InvalidArgument (before): string wasn't Arrayable|iterable|null
+// now infers: Collection<0, 'hello'>

 collect(BackedSuit::Hearts);
-// InvalidArgument (before): enum cases weren't accepted either
+// now infers: Collection<0, BackedSuit>

 collect(null);
-// before: Collection<array-key, mixed> (unbound fallback)
+// now infers: Collection<never, never>

Fixes

  • Fix false UndefinedMagicMethod on custom Eloquent builder subclass methods called after a fluent chain (#1219)
  • Fix false UndefinedMagicMethod on IndexDefinition modifiers in database migrations (#1220)
  • Fix psalm-laravel init on monorepos: no longer puts packages/ into <ignoreFiles>, which silently disabled analysis of package sources (#1214)
  • Surface swallowed bootstrap() failures: a partial Laravel boot now emits a warning by default, and fails the run under failOnInternalError (#1226)

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.14.10...v3.14.11

v4.14.11

Collection type inference for arbitrary inputs, and partial Laravel boots now surface instead of failing silently.

This release bumps min supported Laravel minor versions:

  • ^12.4 to ^12.14
  • ^13.0 to ^13.3

Features

  • Infer collect(), Collection::make(), and LazyCollection::make() return types for arbitrary inputs, not just arrays (#1225)
 collect('hello');
-// InvalidArgument (before): string wasn't Arrayable|iterable|null
+// now infers: Collection<0, 'hello'>

 collect(BackedSuit::Hearts);
-// InvalidArgument (before): enum cases weren't accepted either
+// now infers: Collection<0, BackedSuit>

 collect(null);
-// before: Collection<array-key, mixed> (unbound fallback)
+// now infers: Collection<never, never>

Fixes

  • Surface swallowed bootstrap() failures: a partial Laravel boot now emits a warning by default, and fails the run under failOnInternalError (#1226)

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.14.10...v4.14.11

v3.14.10

A patch release that focused on removing some false positives.

Fixes

  • Fix false TaintedSql on where() calls that pass a column-to-value map (where(['name' => $value])) (#1221)

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.14.9...v3.14.10

v4.14.10

A patch release that removes three false positives around query builders and taint analysis, and fixes a psalm-laravel init misconfiguration on monorepos.

Fixes

  • Fix false TaintedSql on where() calls that pass a column-to-value map (where(['name' => $value])) (#1221)
  • Fix false UndefinedMagicMethod on custom Eloquent builder subclass methods called after a fluent chain (#1219)
  • Fix false UndefinedMagicMethod on IndexDefinition modifiers in database migrations (#1220)
  • Fix psalm-laravel init on monorepos: no longer puts packages/ into <ignoreFiles>, which silently disabled analysis of package sources (#1214)

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.14.9...v4.14.10

v3.14.9

This release improves custom Eloquent builder inference and narrows several stub return types.

Features

  • Infer custom query builders for model instance query methods like newQuery(), newQueryWithoutScopes(), etc. (#1207)

Fixes

  • Narrow getCasts() and getTouchedRelations() return types (#1205)
  • Fix Request::route()/Request::file() default value handling (#1205)

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.14.8...v3.14.9

v4.14.9

This release improves custom Eloquent builder inference and narrows several stub return types.

Features

  • Infer custom query builders for model instance query methods like newQuery(), newQueryWithoutScopes(), etc. (#1207)

Fixes

  • Narrow getCasts() and getTouchedRelations() return types (#1205)
  • Fix Request::route()/Request::file() default value handling (#1205)

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.14.8...v4.14.9

v3.14.8

Patch release fixing Psalm execution on Windows.

Fixes

  • Fix proc_open(): CreateProcess failed warning on Windows by executing psalm through the current PHP binary instead of relying on the shebang (#1189) @HenkPoley

Internal changes

  • Add cross-OS install smoke test (#1197) @alies-dev

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.14.7...v3.14.8

v4.14.8

Patch release fixing Psalm execution on Windows.

Fixes

  • Fix proc_open(): CreateProcess failed warning on Windows by executing psalm through the current PHP binary instead of relying on the shebang (#1189) @HenkPoley

Internal changes

  • Add cross-OS install smoke test (#1197) @alies-dev

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.14.7...v4.14.8

v3.14.7

Fixes caching issue, that makes Psalm complaining about CastsAttributes.

Fixes

  • Fix Psalm cache issue with CastsAttributes: restore user_defined on cast contracts on warm cache (#1188)
  • Fix Arr/Lottery stub shells being removed, which caused UndefinedClass in projects that don't reflect illuminate/support (e.g. laravel/socialite)

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.14.6...v3.14.7

v4.14.7

Fixes caching issue, that makes Psalm complaining about CastsAttributes.

Internal changes

  • Fix Psalm cache issue with CastsAttributes: Restore user_defined on cast contracts on warm cache (#1188)
  • Refactor: reorganize src/ by domain (retire Providers/ and Util/ grab-bags) (#1185)

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.14.6...v4.14.7

v3.14.6

Fixes

  • Narrow sum/avg/min/max return types on relations and collections instead of widening to mixed (#1183)
  • Fix false UndefinedMethod on forwarded Query\Builder methods in custom builder subclasses (#1145)
  • Guard migrator resolution when the app bootstraps partially, avoiding a crash during analysis (#1175)

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.14.5...v3.14.6

v4.14.6

Fixes

  • Narrow sum/avg/min/max return types on relations and collections instead of widening to mixed (#1183)
  • Fix false UndefinedMethod on forwarded Query\Builder methods in custom builder subclasses (#1145)
  • Guard migrator resolution when the app bootstraps partially, avoiding a crash during analysis (#1175)

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.14.5...v4.14.6

v3.14.5

This patch sharpens conditional return types for several Laravel helpers and guards against two crash paths during partial app bootstrap.

Fixes

  • Add conditional return types for Pagination::fragment(), Arr::random(), and Lottery::choose() (#1176)
  • Use a conditional return type for Route::domain() so it narrows $this vs string (#1174)
  • Remap the value type in Paginator::through() to the updated template after the callback (#1173)
  • Guard migrator resolution so analysis no longer crashes when the app bootstraps partially (#1175)
  • Prevent a crash when a container binding resolves to an over-long string (#1179)
  • Forward CLI flags from psalm-laravel analyze through to psalm CLI (#1158)

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.14.4...v3.14.5

v4.14.5

This patch sharpens conditional return types for several Laravel helpers and guards against two crash paths during partial app bootstrap.

Fixes

  • Add conditional return types for Pagination::fragment(), Arr::random(), and Lottery::choose() (#1176)
  • Use a conditional return type for Route::domain() so it narrows $this vs string (#1174)
  • Remap the value type in Paginator::through() to the updated template after the callback (#1173)
  • Guard migrator resolution so analysis no longer crashes when the app bootstraps partially (#1175)
  • Prevent a crash when a container binding resolves to an over-long string (#1179)
  • Forward CLI flags from psalm-laravel analyze through to psalm CLI (#1158)

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.14.4...v4.14.5

v3.14.4

This patch sharpens type inference across collections, the console, and the Date facade, and improves Laravel 11 support by handling Carbon 2.

Features

  • Narrow Command::hasArgument()/hasOption() to literal bool, and fix hasOption() shortcut/negation semantics (#1161)
  • Resolve the configured date class for Date facade static calls (#1157)
  • Infer the named-argument object shape returned by the literal() helper (#1160)
  • Narrow config()->collection() to Collection<key, value> (#1159)
  • Narrow random() return type on Enumerable and LazyCollection (#1152)

Fixes

  • Allow a null option shortcut in Command::getOptions() (#1166)
  • Type the Model::loadCount() constraint closure as Builder (#1164)
  • Allow null values in the __() $replace parameter (#1151)
  • Support Carbon 2 alongside Carbon 3 for better Laravel 11 coverage (#1148)
  • Stop the guard taint warning for SessionGuard::hashPasswordForCookie() on Laravel 11 (#1146)
  • Stop psalm-plugin init from silently disabling type analysis on Psalm 6 (#1144)

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.14.2...v3.14.4

v4.14.4

This patch sharpens type inference across collections, the console, and the Date facade.

Features

  • Narrow Command::hasArgument()/hasOption() to literal bool, and fix hasOption() shortcut/negation semantics (#1161)
  • Resolve the configured date class for Date facade static calls (#1157)
  • Infer the named-argument object shape returned by the literal() helper (#1160)
  • Narrow config()->collection() to Collection<key, value> (#1159)
  • Narrow random() return type on Enumerable and LazyCollection (#1152)

Fixes

  • Allow a null option shortcut in Command::getOptions() (#1166)
  • Type the Model::loadCount() constraint closure as Builder (#1164)
  • Allow null values in the __() $replace parameter (#1151)
  • Stop the guard taint warning for SessionGuard::hashPasswordForCookie() on Laravel 11 (#1146)

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.14.2...v4.14.4

v3.14.2

Patch release: fewer false positives on Laravel's Application contract and uploaded files, plus a simpler (but more powerful and secure) generated CI workflow added via psalm-laravel add ci.

Fixes

  • Resolve concrete-only Application methods (isProduction(), isLocal(), path(), ...) when the receiver is typed on the Contracts\Foundation\Application interface, eliminating false UndefinedInterfaceMethod on app(), ServiceProvider::$app, and Command::$laravel (#1141)
  • 🛡️ Stop false TaintedFile / TaintedSSRF on UploadedFile reads: its only string coercion is the server-controlled temp path, while the user-controlled accessors (contents, client name, MIME type) stay tainted (#1136)
  • Simplify the generated GitHub Actions workflow to a single Psalm job (Psalm 7 runs taint analysis by default) and add CLI-first CI docs (#1132)

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.14.1...v3.14.2

v4.14.2

Patch release: fewer false positives on Laravel's Application contract and uploaded files, plus a simpler (but more powerful and secure) generated CI workflow added via psalm-laravel add ci.

Fixes

  • Resolve concrete-only Application methods (isProduction(), isLocal(), path(), ...) when the receiver is typed on the Contracts\Foundation\Application interface, eliminating false UndefinedInterfaceMethod on app(), ServiceProvider::$app, and Command::$laravel (#1141)
  • 🛡️ Stop false TaintedFile / TaintedSSRF on UploadedFile reads: its only string coercion is the server-controlled temp path, while the user-controlled accessors (contents, client name, MIME type) stay tainted (#1136)
  • Simplify the generated GitHub Actions workflow to a single Psalm job (Psalm 7 runs taint analysis by default) and add CLI-first CI docs (#1132)

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.14.1...v4.14.2

v3.14.1

Patch release for the 3.x (Psalm 6) line. Fixes the init command emitting Psalm 7-only configuration, plus Laravel 11 analysis correctness plus other enhancements and fixes from 4.x branch:

Features

  • Type $this in Artisan::command() closures so command callbacks resolve $this to the command instance (#1122)

Fixes

  • Scope the Artisan::command() $this override to the callback closure so it no longer leaks to surrounding scope (#1127)
  • Fix false UndefinedMethod on app('encrypter') method calls (#1128)
  • Fix false UndefinedMethod on guard methods reached via auth() narrowing (#1121)
  • Type the no-arg higher-order tap() form as HigherOrderTapProxy<T> (#1112)
  • Accept uppercase orderBy() direction ('ASC'/'DESC') on Laravel <13.8 (#1111)
  • Type Query\Builder::orderBy() direction as asc/desc literals plus SortDirection (#1104)
  • Accept an Expression as the $sql argument to Query\Builder::whereRaw() (#1106)
  • Type Filesystem::hash() return as non-empty-string|false (#1109)
  • Accept a single string column on paginators and find() (#1105)
  • Type firstOrNew/updateOrCreate closure values on Laravel 13.5+ (#1102)
  • Type Connection::cursor() rows as stdClass instead of mixed (#1100)
  • Honor case-insensitive validation taint reads (#1099)

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.14.0...v3.14.1

v4.14.1

Patch release focused on Eloquent and query builder type accuracy, plus follow-up fixes to console closures and facade method resolution.

Features

  • Type $this in Artisan::command() closures so command callbacks resolve $this to the command instance (#1122 #1127)

Fixes

  • Fix false UndefinedMethod on app('encrypter') method calls (#1128)
  • Fix false UndefinedMethod on guard methods reached via auth() narrowing (#1121)
  • Type the no-arg higher-order tap() form as HigherOrderTapProxy<T> (#1112)
  • Accept uppercase orderBy() direction ('ASC'/'DESC') on Laravel <13.8 (#1111)
  • Type Query\Builder::orderBy() direction as asc/desc literals plus SortDirection (#1104)
  • Accept an Expression as the $sql argument to Query\Builder::whereRaw() (#1106)
  • Type Filesystem::hash() return as non-empty-string|false (#1109)
  • Accept a single string column on paginators and find() (#1105)
  • Type firstOrNew/updateOrCreate closure values on Laravel 13.5+ (#1102)
  • Type Connection::cursor() rows as stdClass instead of mixed (#1100)
  • Honor case-insensitive validation taint reads (#1099)

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.14.0...v4.14.1

v3.14.0

What’s Changed

v3.14.0 spans Eloquent type inference and security: three new security detectors, relationship and filesystem narrowing, paginator fixes, and an opt-in query-builder best-practice rule.

Security 🛡️

  • Detect user-controlled container resolution as unsafe reflection (CWE-470) (#1075)
  • Detect timing-unsafe comparisons of secrets (CWE-208) (#1013)
  • Add html_url taint kind for URL-context XSS distinct from e() (#1014)

Best Practices ⭐️

  • Add opt-in ImplicitQueryBuilderCall rule for direct model query and scope calls. It requires writing User::query()->where(...) instead of User::where(...) (#1068)

Relationships

  • Fix MissingTemplateParam on in-body belongsToMany()/morphToMany() pivot chains (#1090)
  • Fix mixed collapse when chaining off relation methods, by replacing $this with static in generic templates and using [@template-covariant](https://github.com/template-covariant) for relationships (#1055)

Filesystem

  • Narrow Storage::disk() to FilesystemAdapter so temporaryUrl() and url() resolve (#1093)
  • Narrow FilesystemAdapter listing methods to list<string> (#1094)

Forms

  • Narrow FormRequest magic property reads ($request->field calls) (#1022)

Other Features and Fixes

  • Infer app(Foo::class) as Foo when the booted app cannot resolve it (Laravel packages) (#1076)
  • Fix false-positive UndefinedMethod on $app->when()->needs() chains (#1077)
  • Narrow when()/unless() callback return types (#997)
  • Return the concrete paginator from paginate() and preserve the related-model template through relations (#1082)
  • Suppress false PossiblyUnusedMethod on Eloquent trait boot/initialize hooks (#1080)

Internal changes

  • Raise minimum Laravel 12.x version to ^12.4 (Laravel 11.x is still supported on v3.x plugin) (#1089)
  • CI: add a new /psalm-delta workflow to benchmark plugin over real apps and libs (#1079, #1086, #1084) @alies-dev

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.13.2...v3.14.0

v4.14.0

What's Changed

v4.14.0 spans Eloquent type inference and security: three new security detectors, relationship and filesystem narrowing, paginator fixes, and an opt-in query-builder best-practice rule.

Security 🛡️

  • Detect user-controlled container resolution as unsafe reflection (CWE-470) (#1075)
  • Detect timing-unsafe comparisons of secrets (CWE-208) (#1013)
  • Add html_url taint kind for URL-context XSS distinct from e() (#1014)

Best Practices ⭐️

  • Add opt-in ImplicitQueryBuilderCall rule for direct model query and scope calls. It requires writing User::query()->where(...) instead of User::where(...) (#1068)

Relationships

  • Fix MissingTemplateParam on in-body belongsToMany()/morphToMany() pivot chains (#1090)
  • Fix mixed collapse when chaining off relation methods, by replacing $this with static in generic templates and using [@template-covariant](https://github.com/template-covariant) for relationships (#1055)

Filesystem

  • Narrow Storage::disk() to FilesystemAdapter so temporaryUrl() and url() resolve (#1093)
  • Narrow FilesystemAdapter listing methods to list<string> (#1094)

Forms

  • Narrow FormRequest magic property reads ($request->field calls) (#1022)

Other Features and Fixes

  • Infer app(Foo::class) as Foo when the booted app cannot resolve it (Laravel packages) (#1076)
  • Fix false-positive UndefinedMethod on $app->when()->needs() chains (#1077)
  • Narrow when()/unless() callback return types (#997)
  • Return the concrete paginator from paginate() and preserve the related-model template through relations (#1082)
  • Suppress false PossiblyUnusedMethod on Eloquent trait boot/initialize hooks (#1080)

Internal changes

  • Raise minimum Laravel to ^12.4 (#1089)
  • CI: add a new /psalm-delta workflow to benchmark the plugin over real apps and libraries (#1079, #1086, #1084)

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.13.2...v4.14.0

v3.13.2

What’s Changed

Features

  • Add PublicModelScope and PublicModelAccessor rules for public model scopes and accessors (#1056) @alies-dev
  • Honor value-returning Eloquent scope return types (#1061) @alies-dev

Fixes

Scopes and Eloquent:

  • Report undefined methods on base Builder<Model> from $class::query() (#1073) @alies-dev
  • Resolve higher-order builder where proxies (->orWhere->scope()) (#1066) @alies-dev
  • Suppress unused-method false positives on trait-hosted Eloquent scopes (#1048) @alies-dev
  • Resolve scopes and properties on abstract model base classes (#1058) @alies-dev

Other:

  • Narrow App::make() facade calls to the resolved class (#1072) @alies-dev
  • Fix Carbon dual-purpose method return types on nesbot/carbon >=3.12 (#1060) @alies-dev

Internal changes

  • ci(benchmark): keep Monica beta.5, bump malware-flagged dep instead of downgrading (#1065) @alies-dev

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.13.1...v3.13.2

v4.13.2

What’s Changed

Features

  • Add PublicModelScope and PublicModelAccessor rules for public model scopes and accessors (#1056) @alies-dev
  • Honor value-returning Eloquent scope return types (#1061) @alies-dev

Fixes

Scopes and Eloquent:

  • Report undefined methods on base Builder<Model> from $class::query() (#1073) @alies-dev
  • Resolve higher-order builder where proxies (->orWhere->scope()) (#1066) @alies-dev
  • Suppress unused-method false positives on trait-hosted Eloquent scopes (#1048) @alies-dev
  • Resolve scopes and properties on abstract model base classes (#1058) @alies-dev

Other:

  • Narrow App::make() facade calls to the resolved class (#1072) @alies-dev
  • Fix Carbon dual-purpose method return types on nesbot/carbon >=3.12 (#1060) @alies-dev

Internal changes

  • ci(benchmark): keep Monica beta.5, bump malware-flagged dep instead of downgrading (#1065) @alies-dev

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.13.1...v4.13.2

v3.13.1

What's Changed

Fixes

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.13.0...v3.13.1

v4.13.1

What’s Changed

Fixes

  • Fix trait-hosted #[Scope] detection and scope-vs-QueryBuilder params precedence (#1046) @alies-dev
  • Fix false InvalidArgument on addGlobalScope closures with bare Builder params (#1045) @alies-dev

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.13.0...v4.13.1

v3.13.0

A comprehensive overhaul of Eloquent query-scope analysis: instance scope calls on the base Builder, self/static scope parameters, direct-vs-forwarded dispatch, and variadic / name-collision handling.

Features

  • Resolve instance scope calls on the base Builder to Builder<Model> instead of mixed, type-checking arguments against the scope's declared params (#1032)
  • Resolve self/static scope parameters to the model on custom builders, removing false InvalidArgument and Model&static over-narrowing (#1033)
  • Classify scope calls by PHP dispatch semantics rather than argument shape, so nullable ?Builder, variadic, and non-variable first arguments resolve correctly (#1041)
  • Harden the scope-params hand-off (consume-once) and fix return types when a scope name collides with a real Eloquent\Builder method such as find() (#1042)

Fixes

  • Fix direct scope calls that pass $query explicitly to keep the real method signature, with no left-shifted arguments (#1035)
  • Fix direct scope calls passing $query to use the real return type instead of a fabricated Builder<Model> (#1036)
  • Fix trait-hosted scope self parameters to resolve to the composing class, so a sibling subclass is accepted instead of rejected with a false InvalidArgument (#1043)

Behavior change

  • For a trait composed on an abstract parent, the InvalidArgument message for a bad scope argument now names the composing parent (e.g. AbstractDocument) instead of the queried child (e.g. Contract) (#1031, #1043). No migration needed; the diagnostic is simply more accurate.

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.12.3...v3.13.0

v4.13.0

A comprehensive overhaul of Eloquent query-scope analysis: instance scope calls on the base Builder, self/static scope parameters, direct-vs-forwarded dispatch, and variadic / name-collision handling.

Features

  • Resolve instance scope calls on the base Builder to Builder<Model> instead of mixed, type-checking arguments against the scope's declared params (#1032)
  • Resolve self/static scope parameters to the model on custom builders, removing false InvalidArgument and Model&static over-narrowing (#1033)
  • Classify scope calls by PHP dispatch semantics rather than argument shape, so nullable ?Builder, variadic, and non-variable first arguments resolve correctly (#1041)
  • Harden the scope-params hand-off (consume-once) and fix return types when a scope name collides with a real Eloquent\Builder method such as find() (#1042)

Fixes

  • Fix direct scope calls that pass $query explicitly to keep the real method signature, with no left-shifted arguments (#1035)
  • Fix direct scope calls passing $query to use the real return type instead of a fabricated Builder<Model> (#1036)
  • Fix trait-hosted scope self parameters to resolve to the composing class, so a sibling subclass is accepted instead of rejected with a false InvalidArgument (#1043)

Behavior change

  • For a trait composed on an abstract parent, the InvalidArgument message for a bad scope argument now names the composing parent (e.g. AbstractDocument) instead of the queried child (e.g. Contract) (#1031, #1043). No migration needed; the diagnostic is simply more accurate.

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.12.4...v4.13.0

v4.12.4

What's Changed

The same as v4.12.3 (that was initially tagged on a wrong branch)

Features

Internal changes

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.12.2...v4.12.4

v4.12.3

What’s Changed

⚠️ This version was wrongly tagged on 3.x branch, please ignore it.

v3.12.3

Backported features from v4.12.1 and v4.12.2

Features

  • Narrow $this->input() return type inside FormRequest (#1017) @alies-dev
  • Resolve custom CastsAttributes / Castable casts to real types (#1020) @alies-dev
  • Narrow Collection::where() return types (#1019) @alies-dev

Internal changes

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.12.0...v3.12.3

v4.12.2

What’s Changed

Features

  • Resolve custom CastsAttributes / Castable casts to real types (#1020) @alies-dev
  • Narrow Collection::where() return types (#1019) @alies-dev

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.12.1...v4.12.2

v4.12.1

What's Changed

Fixes

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.12.0...v4.12.1

v2.12.3

What's changed:

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v2.12.2...v2.12.3

v3.12.0

What’s Changed

Features

  • Narrow config() and Repository::get() return types (#1006) @alies-dev
  • Resolve custom Facades in Laravel package source repos (for running on package repos) (#957) @alies-dev

Fixes

  • Specialize Js::from() and Js::encode() taint per call-site (reduce false-positive reports) (#1010) @alies-dev
  • Narrow Request::query() and Request::post() return types (#1009) @alies-dev

Internal changes

  • CI: dedupe push/PR runs and add concurrency cancel (#1008) @alies-dev

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.11.0...v3.12.0

v4.12.0

What’s Changed

Features

  • Narrow config() and Repository::get() return types (#1006) — opt-out by a new resolveConfigReturnTypes config key @alies-dev
  • Resolve custom Facades in Laravel package source repos (for running on package repos) (#957) @alies-dev

Fixes

  • Specialize Js::from() and Js::encode() taint per call-site (reduce false-positive reports) (#1010) @alies-dev
  • Narrow Request::query() and Request::post() return types (#1009) @alies-dev

Internal changes

  • CI: dedupe push/PR runs and add concurrency cancel (#1008) @alies-dev

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.11.0...v4.12.0

v3.11.0

What’s Changed

Features

  • Eloquent improvements:
    • Resolve dynamic where{Column} on Model direct calls (#1001) @alies-dev
    • Narrow Eloquent Builder aggregate (avg(), max(), sum(), etc) returns using a known column type (#1005) @alies-dev
    • Type-check dynamic where{Column} arguments on Eloquent relations (#939) @alies-dev
    • Validate multi-segment dynamic where{Column} method calls (#980) @alies-dev
    • Narrow pluck($value, $key) key type and cover relation chains (#968) @alies-dev
    • Narrow Model::only() return shape from literal keys (#933) @alies-dev
    • Narrow MySQL SET columns to literal union in ModelPropertyHandler (#932) @alies-dev
  • Macroable improvements:
    • Recover macro closure docblocks from vendor packages via AST scan (#994) @alies-dev
    • Use Macroable return type info from docblock Psalm storage (#989) @alies-dev
    • Lock in fluent macro narrowing on closure : static return types (#987) @alies-dev
  • CLI:
    • Add diagnose subcommand for runtime introspection (#959) @alies-dev
    • Add tips for the diagnose command and enhance config created by the init command (#971) @alies-dev
    • Better defaults for psalm-laravel init command @alies-dev
  • Resolve Model::factory()->create() collapse on bare HasFactory (#964) @alies-dev
  • Multi-target facade dispatch for Auth/Cache/Session/Storage/Mail (#907) @alies-dev
  • Narrow auth($name) return to concrete guard class (#981) @alies-dev
  • Narrow Storage::disk() return to Cloud for cloud-driver disks (#982) @alies-dev
  • Resolve Carbon cascade + narrow dual-purpose method returns #922 (#950) @alies-dev
  • Accept variadic strings on Route::middleware facade and RouteRegistrar (#986) @alies-dev
  • Narrow Request::file() via source-level conditional return (#935) @alies-dev

Fixes

  • Dead code mode improvements (PossiblyUnusedMethod):
    • Suppress PossiblyUnusedMethod for legacy scopeXxx() Eloquent methods (#999) @alies-dev
    • Suppress PossiblyUnusedMethod for #[Scope]-attributed Eloquent methods (#998) @alies-dev
  • Anchor config_path() at the project root under Testbench fallback (#949) @alies-dev

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.10.2...v3.11.0

v4.11.0

What’s Changed

Features

  • Eloquent improvements:
    • Resolve dynamic where{Column} on Model direct calls (#1001) @alies-dev
    • Narrow Eloquent Builder aggregate (avg(), max(), sum(), etc) returns using a known column type (#1005) @alies-dev
    • Type-check dynamic where{Column} arguments on Eloquent relations (#939) @alies-dev
    • Validate multi-segment dynamic where{Column} method calls (#980) @alies-dev
    • Narrow pluck($value, $key) key type and cover relation chains (#968) @alies-dev
    • Narrow Model::only() return shape from literal keys (#933) @alies-dev
    • Narrow MySQL SET columns to literal union in ModelPropertyHandler (#932) @alies-dev
  • Macroable improvements:
    • Recover macro closure docblocks from vendor packages via AST scan (#994) @alies-dev
    • Use Macroable return type info from docblock Psalm storage (#989) @alies-dev
    • Lock in fluent macro narrowing on closure : static return types (#987) @alies-dev
  • CLI:
    • Add diagnose subcommand for runtime introspection (#959) @alies-dev
    • Add tips for the diagnose command and enhance config created by the init command (#971) @alies-dev
    • Better defaults for psalm-laravel init command @alies-dev
  • Resolve Model::factory()->create() collapse on bare HasFactory (#964) @alies-dev
  • Multi-target facade dispatch for Auth/Cache/Session/Storage/Mail (#907) @alies-dev
  • Narrow auth($name) return to concrete guard class (#981) @alies-dev
  • Narrow Storage::disk() return to Cloud for cloud-driver disks (#982) @alies-dev
  • Resolve Carbon cascade + narrow dual-purpose method returns #922 (#950) @alies-dev
  • Accept variadic strings on Route::middleware facade and RouteRegistrar (#986) @alies-dev
  • Narrow Request::file() via source-level conditional return (#935) @alies-dev

Fixes

  • Dead code mode improvements (PossiblyUnusedMethod):
    • Suppress PossiblyUnusedMethod for legacy scopeXxx() Eloquent methods (#999) @alies-dev
    • Suppress PossiblyUnusedMethod for #[Scope]-attributed Eloquent methods (#998) @alies-dev
  • Anchor config_path() at the project root under Testbench fallback (#949) @alies-dev

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.10.2...v4.11.0

v3.10.2

What's Changed

Features

Fixes

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.10.1...v3.10.2

v4.10.2

Tighter Request::validated() narrowing, sharper Collection chain inference, and two false-positive fixes in testing + factory flows.

What's Changed

Features

Fixes

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.10.1...v4.10.2

v4.10.1

What's Changed

Features

Fixes

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.10.0...v4.10.1

v3.10.0

What's Changed

Features

Fixes

Internal changes

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.9.2...v3.10.0

v4.10.0

What's Changed

Features

Fixes

Internal changes

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.9.3...v4.10.0

v3.9.3

What's Changed

Improvements

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.9.2...v3.9.3

v4.9.3

What's Changed

Improvements

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.9.2...v4.9.3

v3.9.2

What's Changed

Features & Fixes

Internal changes

New Contributors

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.9.1...v3.9.2

v4.9.2

What's Changed

Features & Fixes

Internal changes

New Contributors

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.9.1...v4.9.2

v3.9.1

What’s Changed

Fixes

  • Fix Psalm crash on AuthManager::__call-forwarded methods (eg auth()->authenticate()) (#856) @alies-dev

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.9.0...v3.9.1

v4.9.1

What’s Changed

Fixes

  • Fix Psalm crash on AuthManager::__call-forwarded methods (eg auth()->authenticate()) (#856) @alies-dev

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.9.0...v4.9.1

v3.9.0

What’s Changed

This release is focused respecting validation rules when to mark input as safe.

Validation & taint analysis

  • Use a more precise taint-escape strategy for validation rules (#819) @alies-dev
  • Extend rule-based taint escape to FormRequest input() / string() / str() accessors (#821) @alies-dev
  • Honour Validation Rule class-level [@psalm-taint-escape](https://github.com/psalm-taint-escape) on custom Rule classes (#826) @alies-dev

Custom Eloquent Builders

  • Preserve fluent return types on custom Eloquent builder subclasses (#845) @alies-dev
  • Fix scopes() chaining on builder contracts (#846) @alies-dev
  • Register custom builder pseudo-method macros (#847) @alies-dev
  • Bind firstOr() callback template across argument positions (#851) @alies-dev

CLI Features

  • New vendor/bin/psalm-laravel CLI with init subcommand for first-time plugin setup (#786) @alies-dev
  • New psalm-laravel add subcommand to scaffold a GitHub Actions security-analysis workflow (#814) @alies-dev

Other type infer Changes

  • Support more Laravel public methods that use variadic parameters: Collection, Session, RedirectResponse, LazyCollection, MessageBag, ServiceProvider(#809, #832) @alies-dev
  • Widen Collection::make / LazyCollection::make / collect() for scalar inputs (#783) @alies-dev
  • Fix InvalidArgument on arrow-function closures in the Builder::where family (#784) @alies-dev
  • Relocate only / except / collect / old to the correct traits (#825) @alies-dev
  • Restate implements / extends in 4 stubs that were wiping reflected metadata (#835, #836) @alies-dev

Internal changes

  • Add StatsHandler to report plugin-level counts under psalm --stats (#817) @alies-dev
  • Include plugin configuration in the bug-report issue body (#781) @alies-dev
v4.9.0

What’s Changed

This release is focused respecting validation rules when to mark input as safe.

Validation & taint analysis

  • Use a more precise taint-escape strategy for validation rules (#819) @alies-dev
  • Extend rule-based taint escape to FormRequest input() / string() / str() accessors (#821) @alies-dev
  • Honour Validation Rule class-level [@psalm-taint-escape](https://github.com/psalm-taint-escape) on custom Rule classes (#826) @alies-dev

Custom Eloquent Builders

  • Preserve fluent return types on custom Eloquent builder subclasses (#845) @alies-dev
  • Fix scopes() chaining on builder contracts (#846) @alies-dev
  • Register custom builder pseudo-method macros (#847) @alies-dev
  • Bind firstOr() callback template across argument positions (#851) @alies-dev

CLI Features

  • New vendor/bin/psalm-laravel CLI with init subcommand for first-time plugin setup (#786) @alies-dev
  • New psalm-laravel add subcommand to scaffold a GitHub Actions security-analysis workflow (#814) @alies-dev

Other type infer Changes

  • Support more Laravel public methods that use variadic parameters: Collection, Session, RedirectResponse, LazyCollection, MessageBag, ServiceProvider(#809, #832) @alies-dev
  • Widen Collection::make / LazyCollection::make / collect() for scalar inputs (#783) @alies-dev
  • Fix InvalidArgument on arrow-function closures in the Builder::where family (#784) @alies-dev
  • Relocate only / except / collect / old to the correct traits (#825) @alies-dev
  • Restate implements / extends in 4 stubs that were wiping reflected metadata (#835, #836) @alies-dev

Internal changes

  • Add StatsHandler to report plugin-level counts under psalm --stats (#817) @alies-dev
  • Include plugin configuration in the bug-report issue body (#781) @alies-dev
v3.8.4

Backport changes from v4.8.2- v4.8.4 releases

What's Changed

  • Narrow AuthManager instance calls, not just the Auth facade (#773) @alies-dev
  • Register Carbon lazy class stubs to prevent MissingDependency errors (#770) @alies-dev
  • Widen Stringable-accepting stubs to reduce ImplicitToStringCast false positives (#775) @alies-dev
  • Tighten filled() to narrow ?string to non-empty-string (#762) @alies-dev
  • fix: narrow app(static::class, ...) and class-string<Foo> arguments (#754) @alies-dev
  • Silence misleading autoloader warning for anonymous Model subclasses (e.g. Laravel Scout) (#769) @alies-dev
  • Stop NoEnvOutsideConfig from firing inside analysed project's config/ (#767) @alies-dev
  • Prevent plugin crashing on invalid Facade aliases by @alies-dev in https://github.com/psalm/psalm-plugin-laravel/pull/746
  • Fix false-positive DocblockTypeContradiction on filled()/blank() guards with nullable strings (#753) @alies-dev

Internal changes

  • Enhance DX with tests (parallel running, optimisations, etc) @alies-dev

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.8.1...v3.8.4

v4.8.4

What’s Changed

This release focuses on fixing minor issues (plugin gaps) found on real projects.

Fixes

  • Narrow AuthManager instance calls, not just the Auth facade (#773) @alies-dev
  • Register Carbon lazy class stubs to prevent MissingDependency errors (#770) @alies-dev
  • Widen Stringable-accepting stubs to reduce ImplicitToStringCast false positives (#775) @alies-dev
  • Tighten filled() to narrow ?string to non-empty-string (#762) @alies-dev
  • Silence misleading autoloader warning for anonymous Model subclasses (e.g. Laravel Scout) (#769) @alies-dev
  • Stop NoEnvOutsideConfig from firing inside analysed project's config/ (#767) @alies-dev

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.8.3...v4.8.4

v4.8.3

What’s Changed

Fixes

  • Fix false-positive DocblockTypeContradiction on filled()/blank() guards with nullable strings (#753) @alies-dev
  • fix: narrow app(static::class, ...) and class-string<Foo> arguments (#754) @alies-dev

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.8.2...v4.8.3

v4.8.2

What’s Changed

Fixes

Internal changes

  • Shorten bug-report title and prevent "vendorsrc" path collapse in IssueUrlGenerator (#747) @alies-dev
  • Tests: Add --SKIPIF-- support to PsalmTest via getSkipReason() (#742) @alies-dev
  • Tests: Run type tests in parallel (use alies-dev/psalm-tester) @alies-dev

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.8.1...v4.8.2

v3.8.1

What's Changed

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.8.0...v3.8.1

v3.8.0

v3.8.0 is a full backport of 4.x features to the Laravel 11–12 + Psalm 6 support line. Everything that shipped in v4.x–4.8 is now available on 3.x.

From this release, almost all new features will be released on both 3.x and 4.x branches.

What's Changed

This release adds psalm-security-analysis AI skill installable via Laravel Boost. You can install it by re-running boost:update (or boost:install on fresh installations). This allows your agent find and fix security issues found by Psalm taint analysis.

Breaking Changes

  • BelongsToMany and MorphToMany stubs now declare 4 template params — migrate BelongsToMany<T, U>BelongsToMany<T, U, Pivot, 'pivot'> (#716) If you documented such relationships directly in your codebase, the migration process is straightforward:
    ./vendor/bin/psalter --plugin=vendor/psalm/plugin-laravel/tools/psalter/UpgradeRelationAnnotations.php
    

Features

  • Narrow env('KEY', $default) return type based on the default argument — env('KEY', 'val')string, env('KEY', false)string|false (#712)
  • Narrow Auth::guard('web') to its concrete class (SessionGuard, TokenGuard) from auth.php config (#711)
  • Narrow Collection::whereNotNull() to remove null from TValue when called without a key (#713)
  • Resolve withCount/withExists/withSum/withMin/withMax/withAvg aggregate accessor properties on Eloquent models without UndefinedMagicPropertyFetch (#715)
  • Validate dispatch() and dispatchIf() arguments against the job/event constructor signature (#726)
  • Infer Carbon (or a custom date class from Date::use()) for now() and today() helpers (#725)
  • Resolve SoftDeletes methods (withTrashed, onlyTrashed, withoutTrashed) on base Builder instances (#727)
  • Type HigherOrderCollectionProxy method call chains precisely — $users->sortByDesc->method() no longer produces InvalidMethodCall (#724)
  • Validate Config::array() and Config::collection() $default argument — scalar fallbacks emit InvalidArgument (#736)
  • Add opt-in <dynamicWhereMethods value="true" /> config to resolve where{Column} calls on relation chains (#714)
  • 🛡️ Mark Http\Client\Response body/header methods (body(), json(), header(), etc.) as taint sources (#676)
  • 🛡️ Add [@psalm-taint-sink](https://github.com/psalm-taint-sink) file to ~30 path-accepting methods in Filesystem, FilesystemAdapter, and LockableFile (#739)

Fixes

  • Fix collect() with no arguments to return Collection<never, never> instead of Collection<array-key, mixed> (#722)
  • Fix Collection::empty() to return static<never, never>, assignable to any typed collection (#679)
  • Narrow Collection::sum() from mixed to int|float (#680)
  • Fix Conditionable::when()/unless() and Tappable::tap() returning mixed on fluent chains — now returns $this (#710)
  • Fix higher-order collection proxy properties ($col->map, $col->each) to carry concrete TKey/TValue types (#720)
  • Narrow Str::replace() return to string when the subject is a string (#719)
  • Add [@psalm-this-out](https://github.com/psalm-this-out) to paginator setCollection() to narrow the type after item replacement (#688)
  • Fix scope methods on Eloquent relation chains — $user->posts()->published()->get() now resolves correctly (#738)
  • 🛡️ Remove false-positive TaintedHtml from Blade view $data parameters — Blade auto-escapes {{ $var }} output (#690)
  • 🛡️ Remove false-positive TaintedSql from PDO-parameterized Builder methods (where, find, having, etc.) (#691)
  • Fix PossiblyUnusedMethod false positives for legacy Eloquent getXxxAttribute()/setXxxAttribute() methods (#732)

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.4.0...v3.8.0

v4.8.1

What’s Changed

  • Enhance AI skill to use compact output mode to save tokens (available from Psalm v7.0.beta-18)
  • Use E_USER_DEPRECATED output type for deprecation warnings

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.8.0...v4.8.1

v4.8.0

Laravel Boost Skill

This release adds psalm-security-analysis AI skill installable via Laravel Boost. You can install it by re-running boost:update (or boost:install on fresh installations). This allows your agent find and fix security issues found by Psalm taint analysis.

What’s Changed

Features

  • Add Laravel Boost psalm-security-analysis skill for AI agents (#672) @alies-dev
  • Support HigherOrderCollectionProxy method call chains (#724) @alies-dev
  • Validate Config::array() and Config::collection() default argument type (#736) @alies-dev
  • Resolve scope methods on Eloquent relation chains (#738) @alies-dev
  • 🛡️ Add missing [@psalm-taint-sink](https://github.com/psalm-taint-sink) file methods to Filesystem/FilesystemAdapter stubs (#739) @alies-dev

Fixes

  • Fix: PossiblyUnusedMethod false positives for Eloquent legacy accessor/mutator methods (#732) @alies-dev

Internal changes

  • Simplify migration: Add Psalter plugin for upgrading relation PHPDoc annotations (#735) @alies-dev

    Migration of PHPDoc from v3.x version to v4.7+ for relationship definitions is easy now:

    ./vendor/bin/psalter --plugin=vendor/psalm/plugin-laravel/tools/psalter/UpgradeRelationAnnotations.php
    

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.7.0...v4.8.0

v4.7.0

What's Changed

This release focuses on Eloquent Builder type coverage — new aggregate accessor resolution (withCount/withExists/withSum/withMin/withMax/withAvg), SoftDeletes on Builder instances, where{Column} dynamic methods on builder and relations, and several stub fixes that restore correct pivot types.

Features

  • Add opt-out dynamic where{Column} method resolution on relation chains (#714)
  • Resolve withCount/withExists/withSum/withMin/withMax/withAvg aggregate accessor properties on Eloquent models (#715)
  • Support SoftDeletes methods resolving on base Builder instances (#727)
  • Update BelongsToMany/MorphToMany stubs to declare 4 template params, restoring pivot types in return values (#716)
  • Infer Carbon for now() and today() helpers (#725)
  • Validate dispatch() arguments against job/event constructor signature (#726)
  • Narrow Auth::guard() return type to the concrete guard class (#711)
  • Narrow Collection::whereNotNull() to remove null from TValue (#713)
  • Narrow env() return type based on the default value argument (#712)

Fixes

  • Fix collect() with no args to return Collection<never, never> (#722)
  • Add [@property-read](https://github.com/property-read) stubs for higher-order collection proxies (#720)
  • Add conditional return type stub for Str::replace() (#719)
  • Stub Conditionable::when()/unless() and Tappable::tap() to fix mixed return on fluent chains (#710)
  • Fix Collection::empty() and Collection::sum() return types (#683)
  • Add [@psalm-this-out](https://github.com/psalm-this-out) to paginator setCollection() (#688)
  • 🛡️ Add [@psalm-taint-escape](https://github.com/psalm-taint-escape) sql to parameterized Builder methods (#691)
  • 🛡️ Remove false-positive TaintedHtml sinks from Blade view data (#690)

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.6.2...v4.7.0

v4.6.2

What’s Changed

Features

  • 🛡️ Add [@psalm-taint-source](https://github.com/psalm-taint-source) input for Http\Client\Response methods (#676) @alies-dev

Improvements

  • Narrow Collection::sum() return type from mixed to int|float (#680) @alies-dev
  • Add Collection::empty() stub with static<never, never> return type (#679) @alies-dev
  • Detect missing views through View facade calls (#668) @alies-dev

Internal changes

  • Support patch-version stub directories (#681) @alies-dev
  • Add taint analysis tests for undertested stub sinks (#675) @alies-dev
  • Refactor test app to Auto Repair Shop domain, reorganize type tests (#667) @alies-dev

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.6.1...v4.6.2

v3.4.0

Backports type inference and taint analysis improvements from Plugin 4.x to Psalm 6 users.

What's Changed

Taint Analysis

  • Cookies — CookieJar make/queue/forever/forget methods flagged as taint-sink header
  • Filesystem — Storage::put(), Storage::prepend(), Storage::append() as path/file sinks
  • HTTP Client — Http::get(), Http::post(), Http::send() as SSRF sinks
  • Sessions — session() helper and Store methods as taint sources (XSS, SQL injection)
  • Views — View::make(), view() helper, View::share() as HTML sinks
  • Mail — Mailable subject/to/from as header sinks, body/line/action as HTML sinks
  • Redis — eval, evalSha, executeRaw as eval sinks
  • Uploaded files — filename, path, contents, MIME type as taint sources
  • Encryption — encrypt()/decrypt() correctly modeled as taint escape/unescape
  • Routing — route parameters as taint sources, redirector as SSRF sink
  • Response — header(), withHeaders(), cookie() as header sinks

Type Inference

Stubs backported from v4.0–v4.6 to reduce false positives:

  • Query Builder — narrowed return types (countint<0,max>, getCollection<int, stdClass>, cursorLazyCollection), added 20+ method stubs (whereNot, having, from, orderBy, etc.)
  • Eloquent Builder — narrowed cursor, pluck, paginators, firstOrCreate; added whereNot, createOrFirst, findSole, chunkMap; @psalm-variadic on with()/without()
  • Model — added Stringable/HasBroadcastChannel implements, public increment/decrement
  • Schema — new stubs for Blueprint, ColumnDefinition, ForeignIdColumnDefinition, ForeignKeyDefinition (fluent migration chains)
  • Auth — new stubs for Authenticatable, SessionGuard, TokenGuard
  • Collection handlers — filter() without callback now removes null/false from TValue; flatten(1)/collapse() preserve TValue

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.3.0...v3.4.0

v4.6.1

What’s Changed

Features

  • Model models variadic arguments: support for static (__callStatic) Model calls (#663) @alies-dev
  • Custom Collections: support returns from Relation method calls (#661) @alies-dev

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.6.0...v4.6.1

v4.6.0

What's Changed

Deep relationship type resolution, Custom query builders, Custom Collections, and smarter validation shapes (thanks to @MDG11).

Custom Query Builders

  • Infer custom query builder types via #[UseEloquentBuilder] attribute and newEloquentBuilder() override (#621) @alies-dev
  • Resolve scope methods on custom query builder instances (#633) @alies-dev
  • Support SoftDeletes trait methods on custom query builders (#632) @alies-dev

Relationships

  • Add MethodForwardingHandler for Relation method forwarding (#642) @alies-dev
  • Resolve morphTo property type from docblock generic annotations (#652) @alies-dev
  • Resolve custom collection types for relation property access (#651) @alies-dev
  • Support #[CollectedBy] attribute for custom Eloquent collections (#623) @alies-dev

Validation

  • Parse dot-notation validation rules into nested array shapes (#625) @MDG11 and @alies-dev

Type Improvements

  • Narrow Collection::flatten() and collapse() return types to preserve TValue (#619) @alies-dev
  • Redeclare Model::increment()/decrement() as public in stub (#618) @alies-dev
  • Skip ModelMakeDiscouraged when model has custom make() method (#616) @alies-dev

Security (Taint Analysis)

  • 🛡️ Add [@psalm-flow](https://github.com/psalm-flow) for Collection get()/first()/pull()/value() default parameter taint propagation (#650) @alies-dev

Internal

  • Replace GNU time with hyperfine + github-action-benchmark (#657) @alies-dev
  • Add CI performance benchmark workflow (#655) @alies-dev

New Contributors

  • @MDG11 made their first contribution in #625 — dot-notation validation rule parsing

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.5.0...v4.6.0

v4.5.0

What's Changed

Three new opt-in rules, expanded taint coverage, and fewer false positives across the board (focus on __() and trans()).

New Rules

  • MissingView: Detect missing Blade view files in view() and View::make() calls (#579) @alies-dev
  • ModelMakeDiscouraged: Detect undefined translation keys in __() and trans() calls (#595) @alies-dev
  • MissingTranslation: Warn against Model::make() in favor of new Model() @alies-dev

Type Improvements

  • Narrow __() and trans() return type to string|array (was mixed) (#592) @alies-dev
  • Narrow __() return to string when the translation key is known to exist @alies-dev
  • Suppress false-positive MissingTemplateParam on HasFactory trait (#517) @alies-dev
  • Skip method forwarding for methods defined directly on Model (#498) @alies-dev
  • Add missing implements clauses to 15 stubs (#615) @alies-dev
  • Fix morphTo stub to bypass $this issue in generics @alies-dev
  • Fix morphToMany/morphedByMany signatures @alies-dev
  • Add [@return](https://github.com/return) static to Stringable stub methods @alies-dev

Security (Taint Analysis)

  • 🛡️ Add [@psalm-taint-source](https://github.com/psalm-taint-source) input for Route parameter methods (#608) @alies-dev
  • 🛡️ Add taint sinks for Redis eval/executeRaw (Lua injection) @alies-dev
  • 🛡️ Add header taint sinks for CookieJar methods @alies-dev
  • 🛡️ Add $path/$domain sinks to Cookie::expire() and forget() @alies-dev
  • 🛡️ Add taint flow tracking through Str::of(), str(), and Stringable @alies-dev
  • 🛡️ Mark Hash::make() and bcrypt() as [@psalm-taint-escape](https://github.com/psalm-taint-escape) system_secret @alies-dev

Benchmark

Tested against 10 real-world Laravel apps (bagisto, coolify, monica, pixelfed, solidtime, unit3d, vito, and others). Combined results vs v4.4.0:

Metric v4.4.0 v4.5.0 Delta
Total issues 84,503 76,123 -9.9%
Plugin-caused false positives 5,115 4,155 -18.8%
Security findings (taint) 83 84 +1

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.4.0...v4.5.0

v3.3.0

Whats' changed

  • feat: update Collection, Model, Builder stubs (backport them from 4.x) @alies-dev

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.2.2...v3.3.0

v3.2.2

What's Changed

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.2.1...v3.2.2

v3.2.1

What's Changed

  • Better type infer for MorphTo relationships @alies-dev

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.2.0...v3.2.1

v3.2.0

What's Changed

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.1.5...v3.2.0

v4.4.0

What’s Changed

This is the biggest release since v4.0.

Is release is focused on Validator and FormRequest classes and provides best-in-class type infer for them.

Features

  • Improve stub type precision across Eloquent, Collections, Query Builder, and helpers to narrow down types (#583) @alies-dev
  • Add validation-aware type narrowing and taint analysis for FormRequest (#577) @alies-dev
  • 🛡️ Add taint-sink sql annotations for SQL identifiers and table names (#582) @alies-dev
  • 🛡️ Add taint sinks for View\Factory and View\View methods (#580) @alies-dev
  • 🛡️ Add taint escape annotations for Js::from() and Js::encode() (#573) @alies-dev
  • 🛡️ Add taint sources for session data retrieval (Session\Store::get() and other) (#557) @alies-dev
  • 🛡️ Add taint sinks for HTTP client SSRF and redirect methods (#555) @alies-dev
  • 🛡️ Add taint sinks for Mail and Notification classes (#556) @alies-dev

Fixes

  • Remove false-positive taint source from Request::integer() and Request::float() (#575) @alies-dev

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.3.2...v4.4.0

v4.3.2

What’s Changed

Dependency plugin v3 plugin v4
PHP ^8.2 ^8.2
Laravel 11, 12 12, 13
Psalm 6, 7 (beta) 7 only

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.3.1...v4.3.2

v4.3.1

What’s Changed

Fixes

  • Accept flexible callable signatures in Attribute::make() (#552)
  • Add [@psalm-taint-escape](https://github.com/psalm-taint-escape) html for e() helper to avoid false negatives (#551)

Internal changes

  • Merge stubs/taintAnalysis/ into stubs/common/ (#553)
  • Add contribution docs for taint analysis

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.3.0...v4.3.1

v4.3.0

What's Changed

This release focuses on migration schema analysis for better Eloquent attribute type inference.

Migration Schema Analysis

  • Support broader Schema call patterns (connection chaining, class constants, custom facades) (#526)
  • Resolve foreignIdFor() column type from referenced model's primary key (#523)
  • Handle Blueprint::datetimes() and fix ulid() default column name (#531)
  • Default to mixed type for unknown Blueprint methods (custom DB types added by macros) (#528)
  • Sort migration files by basename to match Laravel's migrator ordering (#519)
  • Cache parsed migration schema to disk to speed up repeated runs (#524)

Stubs & Type Fixes

  • Fix Collection::map() return type, add Builder::select() and ResponseTrait::cookie() stubs (#548)

Security (Taint Analysis)

  • 🛡️ Add [@psalm-taint-escape](https://github.com/psalm-taint-escape) sql for Connection::escape() (#547)
  • 🛡️ Add taint stubs for UploadedFile and encrypt/decrypt helpers (#546)

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.2.0...v4.3.0

v4.2.0

Highlights

Relationship accessors without generics — The plugin now resolves Eloquent relationship property types even when methods lack generic annotations. Previously, $user->posts required [@return](https://github.com/return) HasMany<Post, User> to get a precise type. Now the plugin parses the method body AST to extract the related model from $this->hasMany(Post::class), falling back gracefully to bounded types.

Static Query Builder methods on ModelsUser::where(...), User::orderBy(...), and model scopes now resolve with the correct Builder<User> return type, enabling full type inference through query chains starting from the model class.

SQL schema dump support — The plugin now parses php artisan schema:dump output (MySQL, PostgreSQL, SQLite) as a base layer for model attribute discovery. PHP migrations are applied on top, matching Laravel's own resolution order.

🛡️ Security: new taint sinks — Added XSS detection through HtmlString (which bypasses Blade escaping) and path traversal detection through Storage facade methods (put, writeStream, delete, copy, move, etc.).

Features

  • Resolve Eloquent relationship accessors without generic annotations (#502)
  • Resolve static Query\Builder methods and scopes on Model classes (#508)
  • Support SQL schema dumps for Eloquent model attribute discovery (#495)
  • Add stubs for Schema\ColumnDefinition, ForeignIdColumnDefinition, and ForeignKeyDefinition fluent methods (#501)
  • 🛡️ Add taint sink for HtmlString to detect XSS bypass of Blade escaping (#491)
  • 🛡️ Add taint sinks for Storage facade / FilesystemAdapter path traversal detection (#492)

Fixes

  • Process Schema calls in migration helper methods, not just up() (#509)
  • Discover Schema/Blueprint calls inside nested block structures (if/else, try/catch, foreach) (#506)
  • Add missing nullableTimestampsTz() switch case in schema aggregator
  • Narrow count/update/increment/decrement return type to int<0, max> (#499)

Improvements

  • Extract cached hasUserPseudoProperty() helper to reduce redundant storage lookups
  • Add $codebase->progress->debug() to relationship resolution catch blocks for --debug traceability
  • Remove silent constructor catch in findStubFiles() — errors now propagate to the top-level handler

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.1.0...v4.2.0

v4.1.0

What’s Changed

Features

  • feat: infer pluck() value type from model [@property](https://github.com/property) annotations (#488) @alies-dev
  • 🛡️ Add taint sinks for Artisan command injection detection (#489) @alies-dev

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.0.1...v4.1.0

v4.0.1

What’s Changed

  • Taint Analysis: add sinks for sub-query builder methods (#481) @alies-dev
  • Narrow Collection::filter() return type when called without callback (#467) @alies-dev
  • Remove route helper function stub as not needed anymore @alies-dev
  • Remove once helper function stub as not needed anymore @alies-dev

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.0.0...v4.0.1

v4.0.0

The biggest release since the plugin was created. 90% of the codebase was rewritten for stability, performance, and deeper Laravel coverage.

Highlights

  • Up to 50x faster on large projects (new caching layer)
  • Extended security scanning -- 9 taint analysis stubs covering SQL injection, shell injection, file traversal, SSRF, XSS, open redirect, and crypto bypass. Taint analysis now runs automatically in Psalm 7 -- no flags needed, just ./vendor/bin/psalm
  • Compatible with Larastan generics -- relationships, pagination, and Attribute<TGet, TSet> templates all work. Use both tools together: Larastan for types, psalm-plugin-laravel for security
  • Removed barryvdh/laravel-ide-helper dependency -- facades and model properties are now resolved natively by the plugin

New features

  • Custom issue checkers: InvalidConsoleArgumentName, InvalidConsoleOptionName, NoEnvOutsideConfig
  • Model [@property](https://github.com/property) declarations take precedence over migration-discovered properties
  • Enhanced attribute type casting -- AST-based casts() parsing without method execution
  • Scope detection -- both legacy scopeXxx() methods and Laravel 12+ #[Scope] attribute, plus the Scope interface
  • Expanded migration types -- after() closures, Blueprint::rename(), addColumn(), vector columns, and auto-discovery of directories registered via loadMigrationsFrom()

Breaking changes

Dependency v3 v4
PHP ^8.2 ^8.3
Laravel 11, 12 12, 13
Psalm 6, 7 (beta) 7 only

Eloquent relation generics now require a declaring model parameter (e.g., BelongsTo<Foo> becomes BelongsTo<Foo, self>).

Internals

  • Internal code type coverage: 100%
  • Tests run 30x faster
  • PER Coding Style 3.0
  • Better DX for testing and contributing

Upgrade

composer require --dev psalm/plugin-laravel:^4.0 -W

Full migration guide

Security scanning coverage

psalm-plugin-laravel is the only free tool that combines Laravel-aware type analysis with dataflow-based taint vulnerability detection:

Vulnerability Laravel surface OWASP
SQL Injection DB::statement(), DB::unprepared(), query builder raw methods A03:2021
Shell Injection Process::run(), Process::pipe() A03:2021
File Traversal Storage::get(), Storage::put(), 15 Filesystem methods A01:2021
SSRF Http::get(), Http::post(), 6 HTTP client methods A10:2021
XSS Response::setContent(), ResponseFactory::make() A03:2021
Open Redirect Redirect::to(), Redirect::away() A10:2021
Crypto tracking Encrypter, HashManager taint-escape/unescape A02:2021

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.1.5...v4.0.0

v4.0.0-rc.2

What’s Changed

See v4.0.0 Beta 1 release for full list of major changes

Migration guide

composer require --dev psalm/plugin-laravel:^4.0@beta -W

If you have "minimum-stability": "stable", and got Your requirements could not be resolved to an installable set of packages.: error

composer config minimum-stability beta
composer config prefer-stable true

composer require --dev vimeo/psalm:^7.0@beta psalm/plugin-laravel:^4.0@RC -W

See Upgrading from v3 to v4 for details.

In this RC:

RC Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.0.0-rc.1...v4.0.0-rc.2

Major Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.1.5...v4.0.0-rc.2

4.0 GitHub Discussion

v4.0.0-rc.1

What's Changed

See v4.0.0 Beta 1 release for full list of major changes

Migration guide

composer require --dev psalm/plugin-laravel:^4.0@beta -W

If you have "minimum-stability": "stable", and got Your requirements could not be resolved to an installable set of packages.: error

composer config minimum-stability beta
composer config prefer-stable true

composer require --dev vimeo/psalm:^7.0@beta psalm/plugin-laravel:^4.0@RC -W

See Upgrading from v3 to v4 for details.

In this RC:

RC/Beta Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.0.0-beta.2...v4.0.0-rc.1

Major Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.1.5...v4.0.0-rc.1

4.0 GitHub Discussion

v4.0.0-beta.2

What’s Changed (from the previous beta)

Beta Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v4.0.0-beta.1...v4.0.0-beta.2

Major Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.1.5...v4.0.0-beta.2

v4.0.0-beta.1

What's Changed

  • Support Laravel 12–13; drop Laravel 11 (and update other dependencies)
  • Require PHP 8.3+; drop PHP 8.2
  • Require Psalm 7; drop Psalm 6
  • Support Model [@property](https://github.com/property) declarations (take precedence over migration-discovered properties)
  • Compatible with Larastan generics
    • Relationships
    • Pagination
    • Attribute
  • Enhanced Model attribute type casting
  • Enhanced Scope detection (legacy scopeXxx() and #[Scope] attribute)
  • Expanded attribute types inferred from migrations (supports more types inc. vector)
  • Speed up to 50x on big projects (caching)
  • Extended taint-analysis support

Internals

  • Remove barryvdh/laravel-ide-helper dependency — facades and model properties are now resolved natively
  • Run tests faster (30x)
  • Internal code type coverage 100%
  • PER3 coding style
  • Better test coverage

Migration guide

composer require --dev psalm/plugin-laravel:^4.0@beta -W

Major Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.1.5...v4.0.0-beta.1

v3.1.5

What’s Changed

  • feat: handle dropColumn() with array argument in SchemaAggregator (#448) @alies-dev

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.1.4...v3.1.5

v3.1.4

What’s Changed

  • Fix false-positive ArgumentTypeCoercion for retry() helper @alies-dev

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.1.3...v3.1.4

v3.1.3

What's Changed

SchemaAggregator improvements (#423, #425)

  • Unsigned integer tracking: unsignedBigInteger, increments, foreignId, id, and the ->unsigned() modifier are now recognized, enabling non-negative-int inference for unsigned columns @alies-dev
  • Default values from migrations: ->default() calls in migrations are now parsed and tracked, enabling more accurate type inference for model attributes with defaults @alies-dev
  • Fix: columns silently dropped: non-method-call statements (like if blocks) inside migration closures no longer cause subsequent column definitions to be skipped @alies-dev
  • Fix: foreignIdFor() column name: foreignIdFor(User::class) now correctly resolves to user_id instead of id @alies-dev

Internal

  • Upgrade to PHPUnit 11.5 (#424) @alies-dev
  • CI: add PHP 8.5 and multi-version Laravel installer testing @alies-dev

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.1.2...v3.1.3

v3.1.2

What’s Changed

  • Update barryvdh/laravel-ide-helper dependency @alies-dev

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.1.1...v3.1.2

v3.1.1

What’s Changed

  • Suppress common Laravel issues with full hierarchy support (#400) @alies-dev

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.1.0...v3.1.1

v3.1.0

What’s Changed

Taint Analysis: Security Analysis in Psalm. Example 1, Example 2

  • Add comprehensive Psalm annotations for taint analysis (#418) @alies-dev
  • Fix false-positive ArgumentTypeCoercion for retry() helper (#417) @alies-dev

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.0.5...v3.1.0

v3.0.5

What’s Changed

  • Update dependencies and internal type info (#416) @alies-dev

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.0.4...v3.0.5

v3.0.4

What’s Changed

  • Update stub for dispatch() match upstream Laravel (#407) @saulens22

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v3.0.3...v3.0.4

v2.12.2

What's Changed

Internal changes:

  • Composer: disableProcessTimeout for a slow test:type @alies-dev
  • Properly initiate GeneratorCommand @alies-dev

Full Changelog: https://github.com/psalm/psalm-plugin-laravel/compare/v2.12.1...v2.12.2

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
codraw/entity-migrator
codraw/doctrine-extra
codraw/aws-tool-kit
codraw/validator
codraw/workflow
codraw/open-api
codraw/cron-job
codraw/process
codraw/log
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony