Skip to content

Commit d83ca25

Browse files
authored
Merge pull request #67 from swisnl/feature/issue-66-unset-relation-using-itemhydrator
Unset relation when null (singular) or empty array (plural)
2 parents ac2105b + 359336d commit d83ca25

File tree

3 files changed

+109
-0
lines changed

3 files changed

+109
-0
lines changed

README.MD

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,8 +372,10 @@ $attributes = [
372372
'name' => 'Björn Brala',
373373
'homepage' => 'https://github.com/bbrala',
374374
],
375+
'co-author' => null,
375376
'date' => '2018-12-02 15:26:32',
376377
'content' => 'JSON:API was originally drafted in May 2013 by Yehuda Katz...',
378+
'media' => [],
377379
'tags' => [
378380
1,
379381
15,
@@ -399,6 +401,12 @@ echo json_encode($itemDocument, JSON_PRETTY_PRINT);
399401
"id": "f1a775ef-9407-40ba-93ff-7bd737888dc6"
400402
}
401403
},
404+
"co-author": {
405+
"data": null
406+
},
407+
"media": {
408+
"data": []
409+
},
402410
"tags": {
403411
"data": [{
404412
"type": "tag",
@@ -426,6 +434,7 @@ echo json_encode($itemDocument, JSON_PRETTY_PRINT);
426434

427435
As you can see in this example, relations can be hydrated by id, or by an associative array with an id and more attributes.
428436
If the item is hydrated using an associative array, it will be included in the resulting json unless `setOmitIncluded(true)` is called on the relation.
437+
You can unset a relation by passing `null` for singular relations or an empty array for plural relations.
429438

430439
N.B. Morph relations require a 'type' attribute to be present in the data in order to know which type of item should be created.
431440

src/ItemHydrator.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
use Illuminate\Support\Str;
77
use Swis\JsonApi\Client\Exceptions\HydrationException;
88
use Swis\JsonApi\Client\Interfaces\ItemInterface;
9+
use Swis\JsonApi\Client\Interfaces\ManyRelationInterface;
10+
use Swis\JsonApi\Client\Interfaces\OneRelationInterface;
911
use Swis\JsonApi\Client\Interfaces\TypeMapperInterface;
1012
use Swis\JsonApi\Client\Relations\HasManyRelation;
1113
use Swis\JsonApi\Client\Relations\HasOneRelation;
@@ -76,6 +78,16 @@ protected function fillRelations(ItemInterface $item, array $attributes): void
7678

7779
$relation = $this->getRelationFromItem($item, $availableRelation);
7880

81+
// The relation should be unset
82+
if (
83+
($relation instanceof OneRelationInterface && $attributes[$availableRelation] === null) ||
84+
($relation instanceof ManyRelationInterface && $attributes[$availableRelation] === [])
85+
) {
86+
$relation->dissociate();
87+
88+
return;
89+
}
90+
7991
// It is a valid relation
8092
if ($relation instanceof HasOneRelation) {
8193
$this->hydrateHasOneRelation($relation, $attributes[$availableRelation]);

tests/ItemHydratorTest.php

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,28 @@ public function it_hydrates_hasone_relationships_with_attributes()
102102
$this->assertArrayHasKey('hasone_relation', $item->toJsonApiArray()['relationships']);
103103
}
104104

105+
/**
106+
* @test
107+
*/
108+
public function it_dissociates_hasone_relationships_when_null()
109+
{
110+
$data = [
111+
'hasone_relation' => null,
112+
];
113+
114+
$item = new WithRelationshipItem();
115+
$item = $this->getItemHydrator()->hydrate($item, $data);
116+
117+
/** @var \Swis\JsonApi\Client\Relations\HasOneRelation $hasOne */
118+
$hasOne = $item->getRelation('hasone_relation');
119+
$this->assertInstanceOf(HasOneRelation::class, $hasOne);
120+
121+
$this->assertNull($hasOne->getIncluded());
122+
123+
$this->assertArrayHasKey('hasone_relation', $item->toJsonApiArray()['relationships']);
124+
$this->assertNull($item->toJsonApiArray()['relationships']['hasone_relation']['data']);
125+
}
126+
105127
/**
106128
* @test
107129
*/
@@ -174,6 +196,28 @@ public function it_hydrates_hasmany_relationships_with_attributes()
174196
$this->assertArrayHasKey('hasmany_relation', $item->toJsonApiArray()['relationships']);
175197
}
176198

199+
/**
200+
* @test
201+
*/
202+
public function it_dissociates_hasmany_relationships_when_empty_array()
203+
{
204+
$data = [
205+
'hasmany_relation' => [],
206+
];
207+
208+
$item = new WithRelationshipItem();
209+
$item = $this->getItemHydrator()->hydrate($item, $data);
210+
211+
/** @var \Swis\JsonApi\Client\Relations\HasManyRelation $hasMany */
212+
$hasMany = $item->getRelation('hasmany_relation');
213+
$this->assertInstanceOf(HasManyRelation::class, $hasMany);
214+
215+
$this->assertTrue($hasMany->getIncluded()->isEmpty());
216+
217+
$this->assertArrayHasKey('hasmany_relation', $item->toJsonApiArray()['relationships']);
218+
$this->assertSame([], $item->toJsonApiArray()['relationships']['hasmany_relation']['data']);
219+
}
220+
177221
/**
178222
* @test
179223
*/
@@ -228,6 +272,28 @@ public function it_hydrates_morphto_relationships_with_attributes()
228272
$this->assertArrayHasKey('morphto_relation', $item->toJsonApiArray()['relationships']);
229273
}
230274

275+
/**
276+
* @test
277+
*/
278+
public function it_dissociates_morphto_relationships_when_null()
279+
{
280+
$data = [
281+
'morphto_relation' => null,
282+
];
283+
284+
$item = new WithRelationshipItem();
285+
$item = $this->getItemHydrator()->hydrate($item, $data);
286+
287+
/** @var \Swis\JsonApi\Client\Relations\MorphToRelation $morphTo */
288+
$morphTo = $item->getRelation('morphto_relation');
289+
$this->assertInstanceOf(MorphToRelation::class, $morphTo);
290+
291+
$this->assertNull($morphTo->getIncluded());
292+
293+
$this->assertArrayHasKey('morphto_relation', $item->toJsonApiArray()['relationships']);
294+
$this->assertNull($item->toJsonApiArray()['relationships']['morphto_relation']['data']);
295+
}
296+
231297
/**
232298
* @test
233299
*/
@@ -350,6 +416,28 @@ public function it_hydrates_morphtomany_relationships_with_attributes()
350416
$this->assertArrayHasKey('morphtomany_relation', $item->toJsonApiArray()['relationships']);
351417
}
352418

419+
/**
420+
* @test
421+
*/
422+
public function it_dissociates_morphtomany_relationships_when_empty_array()
423+
{
424+
$data = [
425+
'morphtomany_relation' => [],
426+
];
427+
428+
$item = new WithRelationshipItem();
429+
$item = $this->getItemHydrator()->hydrate($item, $data);
430+
431+
/** @var \Swis\JsonApi\Client\Relations\MorphToManyRelation $morphToMany */
432+
$morphToMany = $item->getRelation('morphtomany_relation');
433+
$this->assertInstanceOf(MorphToManyRelation::class, $morphToMany);
434+
435+
$this->assertTrue($morphToMany->getIncluded()->isEmpty());
436+
437+
$this->assertArrayHasKey('morphtomany_relation', $item->toJsonApiArray()['relationships']);
438+
$this->assertSame([], $item->toJsonApiArray()['relationships']['morphtomany_relation']['data']);
439+
}
440+
353441
/**
354442
* @test
355443
*/

0 commit comments

Comments
 (0)