|
14 | 14 | namespace ApiPlatform\Laravel\Eloquent\State;
|
15 | 15 |
|
16 | 16 | use ApiPlatform\Metadata\Exception\OperationNotFoundException;
|
| 17 | +use ApiPlatform\Metadata\Exception\RuntimeException; |
17 | 18 | use ApiPlatform\Metadata\GraphQl\Operation;
|
18 | 19 | use ApiPlatform\Metadata\GraphQl\Query;
|
19 | 20 | use ApiPlatform\Metadata\HttpOperation;
|
|
22 | 23 | use Illuminate\Contracts\Foundation\Application;
|
23 | 24 | use Illuminate\Database\Eloquent\Builder;
|
24 | 25 | use Illuminate\Database\Eloquent\Model;
|
| 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; |
25 | 31 |
|
26 | 32 | /**
|
27 | 33 | * @implements LinksHandlerInterface<Model>
|
@@ -101,34 +107,44 @@ private function buildQuery(Builder $builder, Link $link, mixed $identifier): Bu
|
101 | 107 | }
|
102 | 108 |
|
103 | 109 | if ($from = $link->getFromProperty()) {
|
104 |
| - $relation = $this->application->make($link->getFromClass()); |
105 |
| - $relationQuery = $relation->{$from}(); |
106 |
| - if (!method_exists($relationQuery, 'getQualifiedForeignKeyName') && method_exists($relationQuery, 'getQualifiedForeignPivotKeyName')) { |
| 110 | + /** @var Model $relatedInstance */ |
| 111 | + $relatedInstance = $this->application->make($link->getFromClass()); |
| 112 | + $relatedInstance->setAttribute($relatedInstance->getKeyName(), $identifier); |
| 113 | + $relatedInstance->exists = true; |
| 114 | + |
| 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.'); |
| 120 | + } |
| 121 | + |
| 122 | + if ($relation instanceof BelongsTo) { |
107 | 123 | return $builder->getModel()
|
108 | 124 | ->join(
|
109 |
| - $relationQuery->getTable(), // @phpstan-ignore-line |
110 |
| - $relationQuery->getQualifiedRelatedPivotKeyName(), // @phpstan-ignore-line |
111 |
| - $builder->getModel()->getQualifiedKeyName() |
112 |
| - ) |
113 |
| - ->where( |
114 |
| - $relationQuery->getQualifiedForeignPivotKeyName(), // @phpstan-ignore-line |
| 125 | + $relation->getParent()->getTable(), |
| 126 | + $relation->getParent()->getQualifiedKeyName(), |
115 | 127 | $identifier
|
116 |
| - ) |
117 |
| - ->select($builder->getModel()->getTable().'.*'); |
| 128 | + ); |
118 | 129 | }
|
119 | 130 |
|
120 |
| - if (method_exists($relationQuery, 'dissociate')) { |
121 |
| - return $builder->getModel() |
122 |
| - ->join( |
123 |
| - $relationQuery->getParent()->getTable(), // @phpstan-ignore-line |
124 |
| - $relationQuery->getParent()->getQualifiedKeyName(), // @phpstan-ignore-line |
125 |
| - $identifier |
126 |
| - ); |
| 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 | + ); |
127 | 140 | }
|
128 | 141 |
|
129 |
| - 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)); |
130 | 143 | }
|
131 | 144 |
|
132 |
| - return $builder->where($builder->getModel()->qualifyColumn($link->getIdentifiers()[0]), $identifier); |
| 145 | + return $builder->where( |
| 146 | + $builder->getModel()->qualifyColumn($link->getIdentifiers()[0]), |
| 147 | + $identifier |
| 148 | + ); |
133 | 149 | }
|
134 | 150 | }
|
0 commit comments