Skip to content

Commit de5283a

Browse files
committed
refactor: use assert inside fillable relation field classes
1 parent c81334e commit de5283a

File tree

6 files changed

+83
-45
lines changed

6 files changed

+83
-45
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. This projec
55

66
## Unreleased
77

8+
### Changed
9+
10+
- Use `assert()` within fillable relation field classes rather as an optimisation.
11+
812
## [3.1.0] - 2023-10-29
913

1014
### Added

src/Fields/Relations/BelongsTo.php

+20-10
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,11 @@
2020
namespace LaravelJsonApi\Eloquent\Fields\Relations;
2121

2222
use Illuminate\Database\Eloquent\Model;
23-
use Illuminate\Database\Eloquent\Relations\BelongsTo as EloquentBelongsTo;
2423
use LaravelJsonApi\Eloquent\Contracts\FillableToOne;
2524
use LaravelJsonApi\Eloquent\Fields\Concerns\IsReadOnly;
26-
use LogicException;
2725

2826
class BelongsTo extends ToOne implements FillableToOne
2927
{
30-
3128
use IsReadOnly;
3229

3330
/**
@@ -67,17 +64,31 @@ public function mustExist(): bool
6764
*/
6865
public function fill(Model $model, ?array $identifier): void
6966
{
70-
$relation = $model->{$this->relationName()}();
67+
$name = $this->relationName();
7168

72-
if (!$relation instanceof EloquentBelongsTo) {
73-
throw new LogicException('Expecting an Eloquent belongs-to relation.');
74-
}
69+
assert(method_exists($model, $name), sprintf(
70+
'Expecting method %s to exist on model %s.',
71+
$name,
72+
$model::class,
73+
));
74+
75+
$relation = $model->{$name}();
7576

7677
if ($related = $this->find($identifier)) {
78+
assert(method_exists($relation, 'associate'), sprintf(
79+
'Expecting relation class %s to have an "associate" method.',
80+
$relation::class,
81+
));
7782
$relation->associate($related);
78-
} else {
79-
$relation->disassociate();
83+
return;
8084
}
85+
86+
assert(method_exists($relation, 'disassociate'), sprintf(
87+
'Expecting relation class %s to have a "disassociate" method.',
88+
$relation::class,
89+
));
90+
91+
$relation->disassociate();
8192
}
8293

8394
/**
@@ -90,5 +101,4 @@ public function associate(Model $model, ?array $identifier): ?Model
90101

91102
return $model->getRelation($this->relationName());
92103
}
93-
94104
}

src/Fields/Relations/BelongsToMany.php

+14-11
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@
2525
use InvalidArgumentException;
2626
use LaravelJsonApi\Eloquent\Contracts\FillableToMany;
2727
use LaravelJsonApi\Eloquent\Fields\Concerns\IsReadOnly;
28-
use LogicException;
29-
use function get_class;
3028
use function sprintf;
3129

3230
class BelongsToMany extends ToMany implements FillableToMany
@@ -158,17 +156,23 @@ public function detach(Model $model, array $identifiers): iterable
158156
*/
159157
private function getRelation(Model $model): EloquentBelongsToMany
160158
{
161-
$relation = $model->{$this->relationName()}();
159+
$name = $this->relationName();
162160

163-
if ($relation instanceof EloquentBelongsToMany) {
164-
return $relation;
165-
}
161+
assert(method_exists($model, $name), sprintf(
162+
'Expecting method %s to exist on model %s.',
163+
$name,
164+
$model::class,
165+
));
166+
167+
$relation = $model->{$name}();
166168

167-
throw new LogicException(sprintf(
168-
'Expecting relation %s on model %s to be a has-many or morph-many relation.',
169-
$this->relationName(),
170-
get_class($model)
169+
assert($relation instanceof EloquentBelongsToMany, sprintf(
170+
'Expecting method %s on model %s to return a belongs-to-many relation.',
171+
$name,
172+
$model::class,
171173
));
174+
175+
return $relation;
172176
}
173177

174178
/**
@@ -206,5 +210,4 @@ private function getPivotAttributes(Model $parent, Model $related): array
206210

207211
return [];
208212
}
209-
210213
}

src/Fields/Relations/HasMany.php

+20-12
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,17 @@
2525
use Illuminate\Database\Eloquent\Relations\MorphMany as EloquentMorphMany;
2626
use LaravelJsonApi\Eloquent\Contracts\FillableToMany;
2727
use LaravelJsonApi\Eloquent\Fields\Concerns\IsReadOnly;
28-
use LogicException;
2928
use function sprintf;
3029

3130
class HasMany extends ToMany implements FillableToMany
3231
{
33-
32+
/** @var int */
3433
private const KEEP_DETACHED_MODELS = 0;
34+
35+
/** @var int */
3536
private const DELETE_DETACHED_MODELS = 1;
37+
38+
/** @var int */
3639
private const FORCE_DELETE_DETACHED_MODELS = 2;
3740

3841
use IsReadOnly;
@@ -160,19 +163,25 @@ private function doSync(Model $model, EloquentCollection $new): void
160163
* @param Model $model
161164
* @return EloquentHasMany|EloquentMorphMany
162165
*/
163-
private function getRelation(Model $model)
166+
private function getRelation(Model $model): EloquentHasMany|EloquentMorphMany
164167
{
165-
$relation = $model->{$this->relationName()}();
168+
$name = $this->relationName();
166169

167-
if ($relation instanceof EloquentHasMany || $relation instanceof EloquentMorphMany) {
168-
return $relation;
169-
}
170+
assert(method_exists($model, $name), sprintf(
171+
'Expecting method %s to exist on model %s.',
172+
$name,
173+
$model::class,
174+
));
175+
176+
$relation = $model->{$name}();
170177

171-
throw new LogicException(sprintf(
172-
'Expecting relation %s on model %s to be a has-many or morph-many relation.',
173-
$this->relationName(),
174-
get_class($model)
178+
assert($relation instanceof EloquentHasMany || $relation instanceof EloquentMorphMany, sprintf(
179+
'Expecting method %s on model %s to return a belongs-to-many relation.',
180+
$name,
181+
$model::class,
175182
));
183+
184+
return $relation;
176185
}
177186

178187
/**
@@ -228,5 +237,4 @@ private function deleteRelatedModels(EloquentCollection $remove): void
228237
$model->delete();
229238
}
230239
}
231-
232240
}

src/Fields/Relations/HasOne.php

+23-10
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,16 @@
2424
use Illuminate\Database\Eloquent\Relations\MorphOne as EloquentMorphOne;
2525
use LaravelJsonApi\Eloquent\Contracts\FillableToOne;
2626
use LaravelJsonApi\Eloquent\Fields\Concerns\IsReadOnly;
27-
use LogicException;
2827

2928
class HasOne extends ToOne implements FillableToOne
3029
{
31-
30+
/** @var int */
3231
private const KEEP_DETACHED_MODEL = 0;
32+
33+
/** @var int */
3334
private const DELETE_DETACHED_MODEL = 1;
35+
36+
/** @var int */
3437
private const FORCE_DELETE_DETACHED_MODEL = 2;
3538

3639
use IsReadOnly;
@@ -103,14 +106,24 @@ public function mustExist(): bool
103106
*/
104107
public function fill(Model $model, ?array $identifier): void
105108
{
106-
$relation = $model->{$this->relationName()}();
109+
$name = $this->relationName();
107110

108-
if (!$relation instanceof EloquentHasOne && !$relation instanceof EloquentMorphOne) {
109-
throw new LogicException('Expecting an Eloquent has-one or morph-one relation.');
110-
}
111+
assert(method_exists($model, $name), sprintf(
112+
'Expecting method %s to exist on model %s.',
113+
$name,
114+
$model::class,
115+
));
116+
117+
$relation = $model->{$name}();
118+
119+
assert($relation instanceof EloquentHasOne || $relation instanceof EloquentMorphOne, sprintf(
120+
'Expecting method %s on model %s to return a belongs-to-many relation.',
121+
$name,
122+
$model::class,
123+
));
111124

112125
/** @var Model|null $current */
113-
$current = $model->{$this->relationName()};
126+
$current = $model->{$name};
114127
$related = $this->find($identifier);
115128

116129
if ($this->willChange($current, $related)) {
@@ -150,7 +163,7 @@ private function willChange(?Model $current, ?Model $new): bool
150163
* @param EloquentMorphOne|EloquentHasOne $relation
151164
* @param Model $current
152165
*/
153-
private function disassociate($relation, Model $current): void
166+
private function disassociate(EloquentMorphOne|EloquentHasOne $relation, Model $current): void
154167
{
155168
if (self::KEEP_DETACHED_MODEL === $this->detachMode) {
156169
$this->setInverseToNull($relation, $current);
@@ -163,11 +176,11 @@ private function disassociate($relation, Model $current): void
163176
/**
164177
* Disassociate the related model by setting the relationship column(s) to `null`.
165178
*
166-
* @param $relation
179+
* @param EloquentMorphOne|EloquentHasOne $relation
167180
* @param Model $current
168181
* @return void
169182
*/
170-
private function setInverseToNull($relation, Model $current): void
183+
private function setInverseToNull(EloquentMorphOne|EloquentHasOne $relation, Model $current): void
171184
{
172185
if ($relation instanceof EloquentMorphOne) {
173186
$current->setAttribute($relation->getMorphType(), null);

src/Fields/Relations/MorphToMany.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
use Generator;
2323
use Illuminate\Database\Eloquent\Model;
24+
use Illuminate\Support\Collection;
2425
use InvalidArgumentException;
2526
use IteratorAggregate;
2627
use LaravelJsonApi\Contracts\Schema\Container;
@@ -36,7 +37,6 @@
3637

3738
class MorphToMany extends ToMany implements PolymorphicRelation, IteratorAggregate, FillableToMany
3839
{
39-
4040
use Polymorphic;
4141
use IsReadOnly;
4242

@@ -76,7 +76,7 @@ public function __construct(string $fieldName, array $relations)
7676
*/
7777
public function inverseTypes(): array
7878
{
79-
return collect($this->relations)
79+
return Collection::make($this->relations)
8080
->map(fn(ToMany $relation) => $relation->inverse())
8181
->all();
8282
}

0 commit comments

Comments
 (0)