Repository navigation
Conversation
Cover whereNot with scalar, closure and empty-array input, refresh() of mutated values, global scopes around nested where closures (the removed-scope case is version-aware for Laravel 13), related model connection inheritance, and wherePivot()->detach() on a relation without a custom pivot class. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Laravel 13 needs PHP 8.3+, which Composer enforces per install, so the package's own PHP constraint stays at >=8.1. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Testbench deprecated getEnvironmentSetUp() in favour of defineEnvironment(), which exists in Testbench 8 through 11. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Laravel 13 sends an array given to whereNot() straight to the base query builder, so mutated columns were compared against unmutated values. Route the array through a negated nested where instead, using the same rules as Query\Builder::addArrayOfWheres(). This also changes behaviour on Laravel 10-12, where the array went through where() and lost both the negation and the boolean: whereNot(['id' => $id]) used to return the row it should exclude. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Laravel 13 reloads attributes in refreshForUpdate() and, for models that list $refreshes, after every save. Neither goes through refresh(), so mutated attributes kept returning their stale cached values. All of these paths, and refresh() on Laravel 10-13, end in setRawAttributes(), so clear the cache there and drop the refresh() override. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
newPivotQuery() only applied wherePivot() and wherePivotIn(), so detach(), sync(), toggle() and updateExistingPivot() ignored wherePivotNull() constraints and touched every pivot row of the parent. Laravel 13 also applies wherePivotBetween() there. Apply both, in Laravel's order. On Laravel 10-12 this narrows those operations when wherePivotNull() is used, matching Laravel itself. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds Laravel 13 support while keeping Laravel 10, 11 and 12.
Changes
composer.jsonallowslaravel/framework ^13.0andorchestra/testbench ^11.0. The package's PHP constraint stays at>=8.1, since Composer already enforces Laravel 13's PHP 8.3 minimum per install.EloquentBuilder::whereNot(): Laravel 13 sends an array argument straight to the base query builder, so mutated columns were compared against unmutated values (whereNot(['id' => $uuid])excluded nothing). The override routes arrays through a negated nested where, following the same rules asQuery\Builder::addArrayOfWheres().Model::setRawAttributes()now clears the mutator cache. Laravel 13'srefreshForUpdate()and$refreshes(attributes reloaded after save) bypassrefresh(), so mutated attributes kept their stale cached values. Every reload path ends insetRawAttributes()on Laravel 10-13, so therefresh()override is removed.BelongsToMany::newPivotQuery()applieswherePivotNull()constraints, andwherePivotBetween()on Laravel 13, in Laravel's order.defineEnvironment()instead of the deprecatedgetEnvironmentSetUp().Behaviour changes on Laravel 10-12
These are bug fixes, but consumers may notice them:
whereNot([...])now negates. Before, the array went throughwhere()and lost both thenotand the boolean, sowhereNot(['id' => $id])returned the row it should exclude, andorWhereNot([...])behaved asand.wherePivotNull()now narrowsdetach(),sync(),toggle()andupdateExistingPivot()on relations without a custom pivot class. Before, those touched every pivot row of the parent.Testing
17 new tests: characterization tests committed before the upgrade, and acceptance tests committed with each fix (red before, green after). Run locally on PHP 8.3 against SQLite and MySQL 5.6:
The skips are tests for Laravel 13-only APIs. Laravel 13 also passes on PHP 8.5.7.
Not checked locally: whether setup-php installs
imagickon PHP 8.5. The package doesn't need it, so it can be dropped from that leg if the job fails.Known issues not addressed here
Found during review, not caused by Laravel 13:
sync()compares unserialized current ids with serialized new ids, so it detaches and re-attaches already-attached rows.where([...])ignores$boolean, soorWhere([...])behaves asand.where(Closure)that adds no clauses removes the previous clause.using()relations,detach()ignores pivot constraints.🤖 Generated with Claude Code