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.
This commit is contained in:
Vincent Verbruggen
2026-02-20 10:43:24 +01:00
parent a8fdd403b1
commit 1999dbbc11
10 changed files with 1061 additions and 120 deletions

View File

@@ -0,0 +1,138 @@
# 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:
```php
// 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