From f17b4aaddac0e8ac913b4eec4b91b834e0384743 Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki Date: Fri, 31 Oct 2025 11:30:42 +0800 Subject: [PATCH 1/6] [JSON:API] Add `toAttributes()` method Signed-off-by: Mior Muhammad Zaki --- src/Illuminate/Http/Resources/Json/JsonResource.php | 13 ++++++++++++- .../Http/Resources/Json/ResourceCollection.php | 4 ++-- .../JsonApi/AnonymousResourceCollection.php | 2 +- .../JsonApi/Concerns/ResolvesJsonApiElements.php | 5 +++-- .../Http/Resources/JsonApi/JsonApiResourceTest.php | 8 ++++---- 5 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/Illuminate/Http/Resources/Json/JsonResource.php b/src/Illuminate/Http/Resources/Json/JsonResource.php index f98f2cb53e45..f55fc71461e7 100644 --- a/src/Illuminate/Http/Resources/Json/JsonResource.php +++ b/src/Illuminate/Http/Resources/Json/JsonResource.php @@ -111,7 +111,7 @@ protected static function newCollection($resource) */ public function resolve($request = null) { - $data = $this->toArray( + $data = $this->toAttributes( $request ?: Container::getInstance()->make('request') ); @@ -124,6 +124,17 @@ public function resolve($request = null) return $this->filter((array) $data); } + /** + * Transform the resource into an array. + * + * @param \Illuminate\Http\Request $request + * @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable + */ + public function toAttributes(Request $request) + { + return $this->toArray($request); + } + /** * Transform the resource into an array. * diff --git a/src/Illuminate/Http/Resources/Json/ResourceCollection.php b/src/Illuminate/Http/Resources/Json/ResourceCollection.php index 81cfc1bd3181..025ab9b95f42 100644 --- a/src/Illuminate/Http/Resources/Json/ResourceCollection.php +++ b/src/Illuminate/Http/Resources/Json/ResourceCollection.php @@ -96,9 +96,9 @@ public function count(): int * @param \Illuminate\Http\Request $request * @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable */ - public function toArray(Request $request) + public function toAttributes(Request $request) { - return $this->collection->map->toArray($request)->all(); + return $this->collection->map->resolve($request)->all(); } /** diff --git a/src/Illuminate/Http/Resources/JsonApi/AnonymousResourceCollection.php b/src/Illuminate/Http/Resources/JsonApi/AnonymousResourceCollection.php index 4f66aad50947..ebc314652249 100644 --- a/src/Illuminate/Http/Resources/JsonApi/AnonymousResourceCollection.php +++ b/src/Illuminate/Http/Resources/JsonApi/AnonymousResourceCollection.php @@ -35,7 +35,7 @@ public function with($request) * @return array */ #[\Override] - public function toArray(Request $request) + public function toAttributes(Request $request) { return $this->collection ->map(fn ($resource) => $resource->resolveResourceData($request)) diff --git a/src/Illuminate/Http/Resources/JsonApi/Concerns/ResolvesJsonApiElements.php b/src/Illuminate/Http/Resources/JsonApi/Concerns/ResolvesJsonApiElements.php index 909fb7c4416c..5bf8ccd951f7 100644 --- a/src/Illuminate/Http/Resources/JsonApi/Concerns/ResolvesJsonApiElements.php +++ b/src/Illuminate/Http/Resources/JsonApi/Concerns/ResolvesJsonApiElements.php @@ -83,7 +83,7 @@ protected function resolveResourceType(Request $request): string */ protected function resolveResourceAttributes(Request $request): array { - $data = $this->toArray($request); + $data = $this->toAttributes($request); if ($data instanceof Arrayable) { $data = $data->toArray(); @@ -92,6 +92,7 @@ protected function resolveResourceAttributes(Request $request): array } $data = (new Collection($data)) + ->mapWithKeys(fn ($value, $key) => is_int($key) ? [$value => $this->resource->{$value}] : [$key => $value]) ->transform(fn ($value) => value($value, $request)) ->all(); @@ -173,7 +174,7 @@ public function resolveIncludedResources(Request $request): array $relations->push([ 'id' => $uniqueKey[1], 'type' => $uniqueKey[0], - 'attributes' => $resource->toArray($request), + 'attributes' => $resource->resolve($request)['data']['attributes'] ?? [], ]); } diff --git a/tests/Integration/Http/Resources/JsonApi/JsonApiResourceTest.php b/tests/Integration/Http/Resources/JsonApi/JsonApiResourceTest.php index ac95b9af7813..c86b3a5bd261 100644 --- a/tests/Integration/Http/Resources/JsonApi/JsonApiResourceTest.php +++ b/tests/Integration/Http/Resources/JsonApi/JsonApiResourceTest.php @@ -166,7 +166,7 @@ public function toArray(Request $request) class UserApiResource extends JsonApiResource { - public function toArray(Request $request) + public function toAttributes(Request $request) { return [ 'name' => $this->name, @@ -186,11 +186,11 @@ public function user() class PostApiResource extends JsonApiResource { - public function toArray(Request $request) + public function toAttributes(Request $request) { return [ - 'title' => $this->title, - 'content' => $this->content, + 'title', + 'content', ]; } } From b9fbc36be3c25e0950e081e31df561406c42833e Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki Date: Fri, 31 Oct 2025 16:33:23 +0800 Subject: [PATCH 2/6] wip Signed-off-by: Mior Muhammad Zaki --- .../JsonApi/Concerns/ResolvesJsonApiElements.php | 12 ++++++++++-- .../Http/Resources/JsonApi/JsonApiResource.php | 16 ++++++++-------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/Illuminate/Http/Resources/JsonApi/Concerns/ResolvesJsonApiElements.php b/src/Illuminate/Http/Resources/JsonApi/Concerns/ResolvesJsonApiElements.php index 5bf8ccd951f7..91bfe24b05ca 100644 --- a/src/Illuminate/Http/Resources/JsonApi/Concerns/ResolvesJsonApiElements.php +++ b/src/Illuminate/Http/Resources/JsonApi/Concerns/ResolvesJsonApiElements.php @@ -53,6 +53,10 @@ public function resolveResourceData(Request $request): array */ protected function resolveResourceIdentifier(Request $request): string { + if (! is_null($resourceType = $this->toId($request))) { + return $resourceType; + } + if (! $this->resource instanceof Model) { throw ResourceIdentificationException::attemptingToDetermineIdFor($this); } @@ -68,6 +72,10 @@ protected function resolveResourceIdentifier(Request $request): string */ protected function resolveResourceType(Request $request): string { + if (! is_null($resourceType = $this->toType($request))) { + return $resourceType; + } + if (! $this->resource instanceof Model) { throw ResourceIdentificationException::attemptingToDetermineTypeFor($this); } @@ -190,7 +198,7 @@ public function resolveIncludedResources(Request $request): array */ protected function resolveResourceLinks(Request $request): array { - return $this->links($request); + return $this->toLinks($request); } /** @@ -200,7 +208,7 @@ protected function resolveResourceLinks(Request $request): array */ protected function resolveResourceMetaInformation(Request $request): array { - return $this->meta($request); + return $this->toMeta($request); } /** diff --git a/src/Illuminate/Http/Resources/JsonApi/JsonApiResource.php b/src/Illuminate/Http/Resources/JsonApi/JsonApiResource.php index 0c592876a3fb..b595332790d0 100644 --- a/src/Illuminate/Http/Resources/JsonApi/JsonApiResource.php +++ b/src/Illuminate/Http/Resources/JsonApi/JsonApiResource.php @@ -54,21 +54,21 @@ public static function configure(?string $version = null, array $ext = [], array /** * Get the resource's ID. * - * @return string + * @return string|null */ - public function id(Request $request) + public function toId(Request $request) { - return $this->resolveResourceIdentifier($request); + return null; } /** * Get the resource's type. * - * @return string + * @return string|null */ - public function type(Request $request) + public function toType(Request $request) { - return $this->resolveResourceType($request); + return null; } /** @@ -76,7 +76,7 @@ public function type(Request $request) * * @return array */ - public function links(Request $request) + public function toLinks(Request $request) { return $this->jsonApiLinks; } @@ -86,7 +86,7 @@ public function links(Request $request) * * @return array */ - public function meta(Request $request) + public function toMeta(Request $request) { return $this->jsonApiMeta; } From d2a78d66bdebc7635b3ec0658b92c79fd582f5ce Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki Date: Fri, 31 Oct 2025 17:09:16 +0800 Subject: [PATCH 3/6] wip Signed-off-by: Mior Muhammad Zaki --- .../JsonApi/Concerns/ResolvesJsonApiElements.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Illuminate/Http/Resources/JsonApi/Concerns/ResolvesJsonApiElements.php b/src/Illuminate/Http/Resources/JsonApi/Concerns/ResolvesJsonApiElements.php index 91bfe24b05ca..9bbbe6cbad3e 100644 --- a/src/Illuminate/Http/Resources/JsonApi/Concerns/ResolvesJsonApiElements.php +++ b/src/Illuminate/Http/Resources/JsonApi/Concerns/ResolvesJsonApiElements.php @@ -8,6 +8,7 @@ use Illuminate\Http\Request; use Illuminate\Http\Resources\JsonApi\Exceptions\ResourceIdentificationException; use Illuminate\Http\Resources\JsonApi\JsonApiResource; +use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Support\Collection; use Illuminate\Support\Str; use JsonSerializable; @@ -177,12 +178,16 @@ public function resolveIncludedResources(Request $request): array $relations = new Collection; foreach ($this->loadedRelationshipsMap as $relation => $uniqueKey) { - $resource = rescue(fn () => $relation->toResource(), new JsonApiResource($relation), false); + $resourceInstance = rescue(fn () => $relation->toResource(), new JsonApiResource($relation), false); + + if (! $resourceInstance instanceof JsonApiResource && $resourceInstance instanceof JsonResource) { + $resourceInstance = new JsonApiResource($resourceInstance->resource); + } $relations->push([ 'id' => $uniqueKey[1], 'type' => $uniqueKey[0], - 'attributes' => $resource->resolve($request)['data']['attributes'] ?? [], + 'attributes' => Arr::get($resourceInstance->resolve($request), 'data.attributes', []), ]); } From 30b9e3ca239245598cf490accfb7022e9dc98351 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Fri, 31 Oct 2025 09:09:40 +0000 Subject: [PATCH 4/6] Apply fixes from StyleCI --- .../Http/Resources/JsonApi/Concerns/ResolvesJsonApiElements.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Http/Resources/JsonApi/Concerns/ResolvesJsonApiElements.php b/src/Illuminate/Http/Resources/JsonApi/Concerns/ResolvesJsonApiElements.php index 9bbbe6cbad3e..955d645221df 100644 --- a/src/Illuminate/Http/Resources/JsonApi/Concerns/ResolvesJsonApiElements.php +++ b/src/Illuminate/Http/Resources/JsonApi/Concerns/ResolvesJsonApiElements.php @@ -6,9 +6,9 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Http\Request; +use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\JsonApi\Exceptions\ResourceIdentificationException; use Illuminate\Http\Resources\JsonApi\JsonApiResource; -use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Support\Collection; use Illuminate\Support\Str; use JsonSerializable; From 8889879ec667adffabf58162cbcf3bb8bee2b08e Mon Sep 17 00:00:00 2001 From: Mior Muhammad Zaki Date: Fri, 31 Oct 2025 19:32:34 +0800 Subject: [PATCH 5/6] wip Signed-off-by: Mior Muhammad Zaki --- .../Http/Resources/JsonApi/Concerns/ResolvesJsonApiElements.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Illuminate/Http/Resources/JsonApi/Concerns/ResolvesJsonApiElements.php b/src/Illuminate/Http/Resources/JsonApi/Concerns/ResolvesJsonApiElements.php index 955d645221df..d970ddd40905 100644 --- a/src/Illuminate/Http/Resources/JsonApi/Concerns/ResolvesJsonApiElements.php +++ b/src/Illuminate/Http/Resources/JsonApi/Concerns/ResolvesJsonApiElements.php @@ -9,6 +9,7 @@ use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\JsonApi\Exceptions\ResourceIdentificationException; use Illuminate\Http\Resources\JsonApi\JsonApiResource; +use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Illuminate\Support\Str; use JsonSerializable; From a7d72cdadf6c46f66451cb9acd2e3236da7396c3 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Fri, 31 Oct 2025 12:08:26 -0500 Subject: [PATCH 6/6] formatting --- .../Resources/JsonApi/Concerns/ResolvesJsonApiElements.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Illuminate/Http/Resources/JsonApi/Concerns/ResolvesJsonApiElements.php b/src/Illuminate/Http/Resources/JsonApi/Concerns/ResolvesJsonApiElements.php index d970ddd40905..67469fd9c656 100644 --- a/src/Illuminate/Http/Resources/JsonApi/Concerns/ResolvesJsonApiElements.php +++ b/src/Illuminate/Http/Resources/JsonApi/Concerns/ResolvesJsonApiElements.php @@ -55,8 +55,8 @@ public function resolveResourceData(Request $request): array */ protected function resolveResourceIdentifier(Request $request): string { - if (! is_null($resourceType = $this->toId($request))) { - return $resourceType; + if (! is_null($resourceId = $this->toId($request))) { + return $resourceId; } if (! $this->resource instanceof Model) { @@ -181,7 +181,8 @@ public function resolveIncludedResources(Request $request): array foreach ($this->loadedRelationshipsMap as $relation => $uniqueKey) { $resourceInstance = rescue(fn () => $relation->toResource(), new JsonApiResource($relation), false); - if (! $resourceInstance instanceof JsonApiResource && $resourceInstance instanceof JsonResource) { + if (! $resourceInstance instanceof JsonApiResource && + $resourceInstance instanceof JsonResource) { $resourceInstance = new JsonApiResource($resourceInstance->resource); }