Skip to content

Commit cdc3f42

Browse files
themsaidtaylorotwell
authored andcommitted
[5.5] Apply custom pivot model attribute casting on arrays (#21275)
* apply custom pivot model attribute casting when attach and sync are given an array of records * cover case of sync updating existing pivot
1 parent 24356a8 commit cdc3f42

File tree

2 files changed

+95
-6
lines changed

2 files changed

+95
-6
lines changed

src/Illuminate/Database/Eloquent/Relations/Concerns/InteractsWithPivotTable.php

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,9 @@ public function updateExistingPivot($id, array $attributes, $touch = true)
188188
$attributes = $this->addTimestampsToAttachment($attributes, true);
189189
}
190190

191-
$updated = $this->newPivotStatementForId($id)->update($attributes);
191+
$updated = $this->newPivotStatementForId($id)->update(
192+
$this->castAttributes($attributes)
193+
);
192194

193195
if ($touch) {
194196
$this->touchIfTouching();
@@ -236,10 +238,6 @@ protected function formatAttachRecords($ids, array $attributes)
236238
// To create the attachment records, we will simply spin through the IDs given
237239
// and create a new record to insert for each ID. Each ID may actually be a
238240
// key in the array, with extra attributes to be placed in other columns.
239-
$attributes = $this->using
240-
? $this->newPivot()->forceFill($attributes)->getAttributes()
241-
: $attributes;
242-
243241
foreach ($ids as $key => $value) {
244242
$records[] = $this->formatAttachRecord(
245243
$key, $value, $attributes, $hasTimestamps
@@ -263,7 +261,7 @@ protected function formatAttachRecord($key, $value, $attributes, $hasTimestamps)
263261
list($id, $attributes) = $this->extractAttachIdAndAttributes($key, $value, $attributes);
264262

265263
return array_merge(
266-
$this->baseAttachRecord($id, $hasTimestamps), $attributes
264+
$this->baseAttachRecord($id, $hasTimestamps), $this->castAttributes($attributes)
267265
);
268266
}
269267

@@ -503,4 +501,17 @@ protected function castKey($key)
503501
{
504502
return is_numeric($key) ? (int) $key : (string) $key;
505503
}
504+
505+
/**
506+
* Cast the given pivot attributes.
507+
*
508+
* @param array $attributes
509+
* @return array
510+
*/
511+
protected function castAttributes($attributes)
512+
{
513+
return $this->using
514+
? $this->newPivot()->forceFill($attributes)->getAttributes()
515+
: $attributes;
516+
}
506517
}

tests/Integration/Database/EloquentCustomPivotCastTest.php

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,30 @@ public function test_casts_are_respected_on_attach()
6161
$this->assertEquals(['foo' => 'bar'], $project->collaborators[0]->pivot->permissions);
6262
}
6363

64+
public function test_casts_are_respected_on_attach_array()
65+
{
66+
$user = CustomPivotCastTestUser::forceCreate([
67+
'email' => '[email protected]',
68+
]);
69+
70+
$user2 = CustomPivotCastTestUser::forceCreate([
71+
'email' => '[email protected]',
72+
]);
73+
74+
$project = CustomPivotCastTestProject::forceCreate([
75+
'name' => 'Test Project',
76+
]);
77+
78+
$project->collaborators()->attach([
79+
$user->id => ['permissions' => ['foo' => 'bar']],
80+
$user2->id => ['permissions' => ['baz' => 'bar']],
81+
]);
82+
$project = $project->fresh();
83+
84+
$this->assertEquals(['foo' => 'bar'], $project->collaborators[0]->pivot->permissions);
85+
$this->assertEquals(['baz' => 'bar'], $project->collaborators[1]->pivot->permissions);
86+
}
87+
6488
public function test_casts_are_respected_on_sync()
6589
{
6690
$user = CustomPivotCastTestUser::forceCreate([
@@ -76,6 +100,60 @@ public function test_casts_are_respected_on_sync()
76100

77101
$this->assertEquals(['foo' => 'bar'], $project->collaborators[0]->pivot->permissions);
78102
}
103+
104+
public function test_casts_are_respected_on_sync_array()
105+
{
106+
$user = CustomPivotCastTestUser::forceCreate([
107+
'email' => '[email protected]',
108+
]);
109+
110+
$user2 = CustomPivotCastTestUser::forceCreate([
111+
'email' => '[email protected]',
112+
]);
113+
114+
$project = CustomPivotCastTestProject::forceCreate([
115+
'name' => 'Test Project',
116+
]);
117+
118+
$project->collaborators()->sync([
119+
$user->id => ['permissions' => ['foo' => 'bar']],
120+
$user2->id => ['permissions' => ['baz' => 'bar']],
121+
]);
122+
$project = $project->fresh();
123+
124+
$this->assertEquals(['foo' => 'bar'], $project->collaborators[0]->pivot->permissions);
125+
$this->assertEquals(['baz' => 'bar'], $project->collaborators[1]->pivot->permissions);
126+
}
127+
128+
public function test_casts_are_respected_on_sync_array_while_updating_existing()
129+
{
130+
$user = CustomPivotCastTestUser::forceCreate([
131+
'email' => '[email protected]',
132+
]);
133+
134+
$user2 = CustomPivotCastTestUser::forceCreate([
135+
'email' => '[email protected]',
136+
]);
137+
138+
$project = CustomPivotCastTestProject::forceCreate([
139+
'name' => 'Test Project',
140+
]);
141+
142+
$project->collaborators()->attach([
143+
$user->id => ['permissions' => ['foo' => 'bar']],
144+
$user2->id => ['permissions' => ['baz' => 'bar']],
145+
]);
146+
147+
$project->collaborators()->sync([
148+
$user->id => ['permissions' => ['foo1' => 'bar1']],
149+
$user2->id => ['permissions' => ['baz2' => 'bar2']],
150+
]);
151+
152+
$project = $project->fresh();
153+
154+
$this->assertEquals(['foo1' => 'bar1'], $project->collaborators[0]->pivot->permissions);
155+
$this->assertEquals(['baz2' => 'bar2'], $project->collaborators[1]->pivot->permissions);
156+
}
79157
}
80158

81159
class CustomPivotCastTestUser extends Model

0 commit comments

Comments
 (0)