Skip to content

Commit

Permalink
[10.x] Adds updateOrCreate on HasManyThrough relations regression t…
Browse files Browse the repository at this point in the history
…est (#48533)

* Add test to replicate situation

* Failing test

* Update test

* WIP

* WIP

* Clean up the test a bit

* Avoid manually setting the ID

---------

Co-authored-by: Ralph J. Smit <[email protected]>
  • Loading branch information
tonysm and ralphjsmit authored Sep 25, 2023
1 parent 246b2f4 commit efaeefe
Showing 1 changed file with 44 additions and 0 deletions.
44 changes: 44 additions & 0 deletions tests/Integration/Database/EloquentHasManyThroughTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,50 @@ public function testHasSameParentAndThroughParentTable()

$this->assertEquals([1], $categories->pluck('id')->all());
}

public function testUpdateOrCreateAffectingWrongModelsRegression()
{
// On Laravel 10.21.0, a bug was introduced that would update the wrong model when using `updateOrCreate()`,
// because the UPDATE statement would target a model based on the ID from the parent instead of the actual
// conditions that the `updateOrCreate()` targeted. This test replicates the case that causes this bug.

$team1 = Team::create();
$team2 = Team::create();

// Jane's ID should be the same as the $team1's ID for the bug to occur.
$jane = User::create(['name' => 'Jane', 'slug' => 'jane-slug', 'team_id' => $team2->id]);
$john = User::create(['name' => 'John', 'slug' => 'john-slug', 'team_id' => $team1->id]);

$taylor = User::create(['name' => 'Taylor']);
$team1->update(['owner_id' => $taylor->id]);

$this->assertSame(2, $john->id);
$this->assertSame(1, $jane->id);

$this->assertSame(2, $john->refresh()->id);
$this->assertSame(1, $jane->refresh()->id);

$this->assertSame('john-slug', $john->slug);
$this->assertSame('jane-slug', $jane->slug);

$this->assertSame('john-slug', $john->refresh()->slug);
$this->assertSame('jane-slug', $jane->refresh()->slug);

// The `updateOrCreate` method would first try to find a matching attached record with a query like:
// `->where($attributes)->first()`, which should return `John` of ID 1 in our case. However, it'd
// return the incorrect ID of 2, which caused it to update Jane's record instead of John's.

$taylor->teamMates()->updateOrCreate([
'name' => 'John',
], [
'slug' => 'john-doe',
]);

// Expect $john's slug to be updated to john-doe instead of john-slug.
$this->assertSame('john-doe', $john->fresh()->slug);
// $jane should not be updated, because it belongs to a different user altogether.
$this->assertSame('jane-slug', $jane->fresh()->slug);
}
}

class User extends Model
Expand Down

0 comments on commit efaeefe

Please sign in to comment.