Files
Obsidian-Vault/Work/Projects/Laravel-v12-Migration/Logs/upgrade-log-qlshandling.md
Vincent Verbruggen 1999dbbc11 Add upgrade logs for Laravel 11 to 12 migration across multiple projects
- Created detailed upgrade log for deversspecialist with phases including Composer updates, Filament upgrades, Tailwind migration, Pest updates, and final verification.
- Added upgrade log for goos project, documenting version changes, encountered issues, and resolutions during the migration process.
- Documented Composer dependency upgrades for qlshandling, highlighting significant changes and necessary code adjustments.
- Introduced a template for future upgrade logs to standardize documentation for Laravel migrations.
2026-02-20 10:43:24 +01:00

6.9 KiB

Composer Dependency Upgrades - Feb 2026

Summary of Upgrades

Package From To Code Changes
spatie/laravel-data 4.14.0 4.19.1 Constraint only ("4.14" -> "^4.14")
spatie/eloquent-sortable 4.5.2 5.0.0 None
resend/resend-laravel 0.17.0 1.2.0 None
symfony/http-client 7.4.5 8.x None
symfony/mailgun-mailer 7.4.0 8.x None
darkaonline/l5-swagger 9.0.1 10.x None
livewire/livewire 3.7.10 4.x Config key renames
laravel/passport 12.4.2 13.x Middleware, service provider, factory override, test updates

Livewire 3 -> 4

Config Changes (config/livewire.php)

Old Key New Key
layout component_layout
lazy_placeholder component_placeholder

What We Didn't Need to Change

  • wire:model behavior: Our usage (wire:model="barcode" without .live) works the same in v4 (deferred by default in both v3 and v4).
  • wire-elements/modal v3.0.4: Already compatible with Livewire 4 (requires ^3.2.3|^4.0).
  • Route::get() with Livewire component: Still works in v4. Route::livewire() is recommended but not required.
  • Component tag closing: All our <livewire:> tags were already properly self-closed.
  • wire:transition / wire:scroll: Not used in this app.

Potential Gotchas for Next Time

  • wire:model.blur / .change behavior changed: In v4, these modifiers now control client-side state sync timing too. Add .live before them if you want old behavior: wire:model.live.blur.
  • Component tags must be closed: Unclosed <livewire:component> tags are interpreted as slot content in v4.
  • @livewireStyles/@livewireScripts: Still work with inject_assets => true, but you can use @livewireScriptConfig if bundling Livewire into your JS build.

Laravel Passport 12 -> 13

Breaking Changes Encountered

1. Passport::hashClientSecrets() Removed

Secrets are now ALWAYS hashed in v13. Remove all calls to Passport::hashClientSecrets().

Files fixed:

  • modules/Auth/AuthServiceProvider.php - Removed the call
  • tests/Feature/Scopes/Api/Http/Middleware/CheckDecoCredentialsTest.php - Removed from tests

2. CheckClientCredentials Middleware Renamed to CheckToken

All credential-checking middleware were renamed:

Old Name New Name
CheckClientCredentials CheckToken
CheckClientCredentialsForAnyScope CheckTokenForAnyScope
CheckScopes CheckToken
CheckForAnyScope CheckTokenForAnyScope
CheckCredentials (abstract) ValidateToken

Files fixed:

  • app/Http/Kernel.php - Updated import and all 3 middleware group references

3. ClientRepository::create() Now Protected

The create() method on ClientRepository is now protected. Use the named factory methods instead:

Old New
$repo->create(null, $name, '') $repo->createClientCredentialsGrantClient($name)
$repo->createPersonalAccessClient(...) $repo->createPersonalAccessGrantClient($name)

The new methods return a Client with $client->plainSecret property containing the unhashed secret.

Files fixed:

  • tests/Feature/Http/Controllers/Api/V1/AirWaybillMilestone/AirWaybillMilestoneControllerTest.php
  • tests/Feature/Scopes/Api/Http/Middleware/CheckDecoCredentialsTest.php
  • scopes/Api/Tests/Http/Controllers/V1/Outbound/PickupControllerTest.php
  • scopes/Api/Tests/Pest.php

4. setSecretAttribute() No Longer Exists

Passport 13 uses an Eloquent Attribute mutator for secret that auto-hashes on assignment. Instead of manually setting secrets:

// Old (v12)
$client->setSecretAttribute($secret);
$client->save();

// New (v13) - just set the attribute, it auto-hashes
$client->secret = $secret;
$client->save();

// Or better - use the factory/repository which exposes plainSecret
$client = $repo->createClientCredentialsGrantClient($name);
$plainSecret = $client->plainSecret; // Available immediately after creation

5. No Database Migration Needed (Backward Compatible)

Passport 13 introduces new column names (owner_type/owner_id, redirect_uris, grant_types, scopes) but is fully backward compatible with the old schema:

  • ClientRepository::create() auto-detects columns via getColumnListing() and writes to whichever exist
  • Client::redirectUris() accessor falls back to reading redirect column
  • Client::grantTypes() accessor infers from personal_access_client/password_client columns
  • Client::firstParty() checks for user_id first, falls back to owner_id

The Passport 13 factory writes to new columns, so we override it with modules/Auth/Database/Factories/ClientFactory.php that maps to the old schema. The Client model's newFactory() method returns our custom factory.

6. config/passport.php Cleanup

Removed deprecated config keys:

  • client_uuids - UUIDs are now always used (default in v13)
  • personal_access_client - Personal access clients table removed

What We Didn't Need to Change

  • Passport::useTokenModel() - Still works the same
  • Passport::useClientModel() - Still works the same
  • Passport::ignoreRoutes() - Still works
  • Token model (custom) extending Laravel\Passport\Token - Still compatible
  • AccessTokenController - Still exists, TokenController still extends it
  • auth('passport')->client() - Still works in middleware
  • Token::findFromRequest() - Still works (JWT parsing unchanged)

Production Deployment Notes

  • No database migration required - Passport 13 is backward compatible with the old schema
  • Existing hashed secrets remain valid since v12 was already hashing them
  • If you want to migrate to the new schema in the future, see https://github.com/laravel/passport/blob/13.x/UPGRADE.md for the official migration
  • The oauth_personal_access_clients table is redundant in v13 and can be dropped
  • When migrating to new schema: remove the custom ClientFactory override and newFactory() from the Client model