Skip to content

Commit 997fec0

Browse files
committed
Use built in eloquent methods
1 parent dc53b75 commit 997fec0

File tree

2 files changed

+44
-25
lines changed

2 files changed

+44
-25
lines changed

src/Laravel/Eloquent/State/LinksHandler.php

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
namespace ApiPlatform\Laravel\Eloquent\State;
1515

1616
use ApiPlatform\Metadata\Exception\OperationNotFoundException;
17+
use ApiPlatform\Metadata\Exception\RuntimeException;
1718
use ApiPlatform\Metadata\GraphQl\Operation;
1819
use ApiPlatform\Metadata\GraphQl\Query;
1920
use ApiPlatform\Metadata\HttpOperation;
@@ -22,7 +23,11 @@
2223
use Illuminate\Contracts\Foundation\Application;
2324
use Illuminate\Database\Eloquent\Builder;
2425
use Illuminate\Database\Eloquent\Model;
25-
use Illuminate\Database\Eloquent\Relations\MorphOneOrMany;
26+
use Illuminate\Database\Eloquent\Relations\BelongsTo;
27+
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
28+
use Illuminate\Database\Eloquent\Relations\HasOneOrMany;
29+
use Illuminate\Database\Eloquent\Relations\MorphTo;
30+
use Illuminate\Database\Eloquent\Relations\Relation;
2631

2732
/**
2833
* @implements LinksHandlerInterface<Model>
@@ -102,41 +107,44 @@ private function buildQuery(Builder $builder, Link $link, mixed $identifier): Bu
102107
}
103108

104109
if ($from = $link->getFromProperty()) {
105-
$relation = $this->application->make($link->getFromClass());
106-
$relationQuery = $relation->{$from}();
110+
/** @var Model $relatedInstance */
111+
$relatedInstance = $this->application->make($link->getFromClass());
112+
$relatedInstance->setAttribute($relatedInstance->getKeyName(), $identifier);
113+
$relatedInstance->exists = true;
107114

108-
if ($relationQuery instanceof MorphOneOrMany) {
109-
return $builder
110-
->where($relationQuery->getForeignKeyName(), $identifier)
111-
->where($relationQuery->getMorphType(), $relationQuery->getMorphClass());
115+
/** @var Relation<Model, Model, mixed> $relation */
116+
$relation = $relatedInstance->{$from}();
117+
118+
if ($relation instanceof MorphTo) {
119+
throw new RuntimeException('Cannot query directly from a MorphTo relationship.');
112120
}
113121

114-
if (!method_exists($relationQuery, 'getQualifiedForeignKeyName') && method_exists($relationQuery, 'getQualifiedForeignPivotKeyName')) {
122+
if ($relation instanceof BelongsTo) {
115123
return $builder->getModel()
116124
->join(
117-
$relationQuery->getTable(), // @phpstan-ignore-line
118-
$relationQuery->getQualifiedRelatedPivotKeyName(), // @phpstan-ignore-line
119-
$builder->getModel()->getQualifiedKeyName()
120-
)
121-
->where(
122-
$relationQuery->getQualifiedForeignPivotKeyName(), // @phpstan-ignore-line
125+
$relation->getParent()->getTable(),
126+
$relation->getParent()->getQualifiedKeyName(),
123127
$identifier
124-
)
125-
->select($builder->getModel()->getTable().'.*');
128+
);
126129
}
127130

128-
if (method_exists($relationQuery, 'dissociate')) {
129-
return $builder->getModel()
130-
->join(
131-
$relationQuery->getParent()->getTable(), // @phpstan-ignore-line
132-
$relationQuery->getParent()->getQualifiedKeyName(), // @phpstan-ignore-line
133-
$identifier
134-
);
131+
if ($relation instanceof HasOneOrMany || $relation instanceof BelongsToMany) {
132+
return $relation->getQuery();
133+
}
134+
135+
if (method_exists($relation, 'getQualifiedForeignKeyName')) {
136+
return $relation->getQuery()->where(
137+
$relation->getQualifiedForeignKeyName(),
138+
$identifier
139+
);
135140
}
136141

137-
return $builder->getModel()->where($relationQuery->getQualifiedForeignKeyName(), $identifier);
142+
throw new RuntimeException(\sprintf('Unhandled or unknown relationship type: %s for property %s on %s', $relation::class, $from, $relatedInstance::class));
138143
}
139144

140-
return $builder->where($builder->getModel()->qualifyColumn($link->getIdentifiers()[0]), $identifier);
145+
return $builder->where(
146+
$builder->getModel()->qualifyColumn($link->getIdentifiers()[0]),
147+
$identifier
148+
);
141149
}
142150
}

src/Laravel/Tests/EloquentTest.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,17 @@ public function testBelongsTo(): void
447447
$this->assertEquals($json['sons'][0], '/api/grand_sons/1');
448448
}
449449

450+
public function testHasMany(): void
451+
{
452+
GrandSonFactory::new()->count(1)->create();
453+
454+
$res = $this->get('/api/grand_fathers/1/grand_sons', ['Accept' => ['application/ld+json']]);
455+
$json = $res->json();
456+
$this->assertEquals($json['@id'], '/api/grand_fathers/1/grand_sons');
457+
$this->assertEquals($json['totalItems'], 1);
458+
$this->assertEquals($json['member'][0]['@id'], '/api/grand_sons/1');
459+
}
460+
450461
public function testRelationIsHandledOnCreateWithNestedData(): void
451462
{
452463
$cartData = [

0 commit comments

Comments
 (0)