Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
c69a2e5
[JSON:API] Supports `JsonApiResource::toRelationships()`
crynobone Nov 3, 2025
cd01fa7
Apply fixes from StyleCI
StyleCIBot Nov 3, 2025
ec25825
wip
crynobone Nov 4, 2025
9a0a8fe
Apply fixes from StyleCI
StyleCIBot Nov 4, 2025
3ee71cc
wip
crynobone Nov 4, 2025
096ce53
Merge remote-tracking branch 'upstream/json-api-resource' into json-a…
crynobone Nov 4, 2025
5a3f43f
wip
crynobone Nov 4, 2025
6de34f6
Update JsonApiResource.php
taylorotwell Nov 4, 2025
04e0d2e
only include relationship if defined
taylorotwell Nov 4, 2025
a89fd69
formatting
taylorotwell Nov 4, 2025
b0eaf03
tweak how relations work
taylorotwell Nov 4, 2025
04bfaad
work on relationships
taylorotwell Nov 4, 2025
2479bae
fixes implementation
crynobone Nov 5, 2025
f2ffda0
Add `JsonApiRequest`
crynobone Nov 5, 2025
04fc800
Apply fixes from StyleCI
StyleCIBot Nov 5, 2025
2e56f97
wip
crynobone Nov 5, 2025
caf5c9c
Merge remote-tracking branch 'upstream/json-api-resource-relations' i…
crynobone Nov 5, 2025
334b9c2
wip
crynobone Nov 5, 2025
5930c7d
wip
crynobone Nov 5, 2025
0828655
wip
crynobone Nov 5, 2025
4a09643
formatting
taylorotwell Nov 5, 2025
2b7861e
wip
crynobone Nov 6, 2025
51f5f9f
Apply fixes from StyleCI
StyleCIBot Nov 6, 2025
227ef2a
wip
crynobone Nov 6, 2025
a7ec8d0
Apply fixes from StyleCI
StyleCIBot Nov 6, 2025
a949f45
wip
crynobone Nov 6, 2025
1fcd9a7
Apply fixes from StyleCI
StyleCIBot Nov 6, 2025
3cde253
Add `make:resource` with `--json-api` option
crynobone Nov 6, 2025
a9d041d
Apply suggestions from code review
crynobone Nov 6, 2025
f59070b
ensure request is always `JsonApiRequest`
crynobone Nov 7, 2025
d320641
wip
crynobone Nov 7, 2025
4ae7eb7
wip
crynobone Nov 7, 2025
2e6d941
Apply fixes from StyleCI
StyleCIBot Nov 7, 2025
64cacc9
wip
crynobone Nov 7, 2025
5748a9f
wip
crynobone Nov 7, 2025
acbde38
Apply fixes from StyleCI
StyleCIBot Nov 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ public function with($request)
'included' => $this->collection
->map(fn ($resource) => $resource->resolveIncludedResources($request))
->flatten(depth: 1)
->uniqueStrict(fn ($relation): array => [$relation['id'], $relation['type']])
->all(),
...($implementation = JsonApiResource::$jsonApiInformation)
? ['jsonapi' => $implementation]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\AsPivot;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\Pivot;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
Expand Down Expand Up @@ -138,6 +141,8 @@ protected function compileResourceRelationships(Request $request): void
return;
}

$this->resource->loadMissing($this->toRelationships($request));

$this->loadedRelationshipsMap = new WeakMap;

$this->loadedRelationshipIdentifiers = (new Collection($this->resource->getRelations()))
Expand All @@ -147,55 +152,70 @@ protected function compileResourceRelationships(Request $request): void
return [$key => ['data' => $relations]];
}

$relationship = $this->resource->{$key}();

$isUnique = ! $relationship instanceof BelongsToMany;

$key = static::resourceTypeFromModel($relations->first());

return [$key => ['data' => $relations->map(function ($relation) use ($key) {
return transform([$key, static::resourceIdFromModel($relation)], function ($uniqueKey) use ($relation) {
$this->loadedRelationshipsMap[$relation] = $uniqueKey;
return [$key => ['data' => $relations->map(function ($relation) use ($key, $isUnique) {
return transform([$key, static::resourceIdFromModel($relation)], function ($uniqueKey) use ($relation, $isUnique) {
$this->loadedRelationshipsMap[$relation] = [...$uniqueKey, $isUnique];

return ['id' => $uniqueKey[1], 'type' => $uniqueKey[0]];
});
})]];
}

return [$key => ['data' => transform(
if (is_null($relations) || $relations instanceof Pivot || in_array(AsPivot::class, class_uses_recursive($relations), true)) {
return [$key => null];
}

return [$key => ['data' => [transform(
[static::resourceTypeFromModel($relations), static::resourceIdFromModel($relations)],
function ($uniqueKey) use ($relations) {
$this->loadedRelationshipsMap[$relations] = $uniqueKey;
$this->loadedRelationshipsMap[$relations] = [...$uniqueKey, true];

return ['id' => $uniqueKey[1], 'type' => $uniqueKey[0]];
}
)]];
})->all();
)]]];
})->filter()->all();
}

/**
* Resolves `included` for the resource.
*/
public function resolveIncludedResources(Request $request): array
{
if (! $this->resource instanceof Model) {
return [];
}

$this->compileResourceRelationships($request);

$relations = new Collection;

foreach ($this->loadedRelationshipsMap as $relation => $uniqueKey) {
foreach ($this->loadedRelationshipsMap as $relation => $value) {
$resourceInstance = rescue(fn () => $relation->toResource(), new JsonApiResource($relation), false);

if (! $resourceInstance instanceof JsonApiResource &&
$resourceInstance instanceof JsonResource) {
$resourceInstance = new JsonApiResource($resourceInstance->resource);
}

[$type, $id, $isUnique] = $value;

$relations->push([
'id' => $uniqueKey[1],
'type' => $uniqueKey[0],
'id' => $id,
'type' => $type,
'_uniqueKey' => $isUnique === true ? [$id, $type] : [$id, $type, (string) Str::random()],
'attributes' => Arr::get($resourceInstance->resolve($request), 'data.attributes', []),
]);
}

return $relations->uniqueStrict(
fn ($relation): array => [$relation['id'], $relation['type']]
)->all();
return $relations->uniqueStrict(fn ($relation): array => $relation['_uniqueKey'])
->map(fn ($relation): array => Arr::except($relation, ['_uniqueKey']))
->all();
}

/**
Expand Down
9 changes: 9 additions & 0 deletions src/Illuminate/Http/Resources/JsonApi/JsonApiResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ public static function configure(?string $version = null, array $ext = [], array
]);
}

public function toRelationships(Request $request)
{
if (property_exists($this, 'relationships')) {
return $this->relationships;
}

return [];
}

/**
* Get the resource's ID.
*
Expand Down
Loading
Loading