Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
fce2a2e
wip
crynobone Oct 23, 2025
a00cd30
wip
crynobone Oct 28, 2025
6457e72
Apply fixes from StyleCI
StyleCIBot Oct 28, 2025
5d15ab7
wip
crynobone Oct 28, 2025
2214970
Merge remote-tracking branch 'origin/json-api-resource' into json-api…
crynobone Oct 28, 2025
6116f06
Apply fixes from StyleCI
StyleCIBot Oct 28, 2025
c703cf8
wip
crynobone Oct 28, 2025
b219e6d
wip
crynobone Oct 29, 2025
8d2da32
Apply fixes from StyleCI
StyleCIBot Oct 29, 2025
e7de423
wip
crynobone Oct 29, 2025
882ed31
Apply fixes from StyleCI
StyleCIBot Oct 29, 2025
3d75b4c
wip
crynobone Oct 29, 2025
4aa295d
wip
crynobone Oct 29, 2025
d945d9f
Apply fixes from StyleCI
StyleCIBot Oct 29, 2025
c2d7dfc
wip
crynobone Oct 30, 2025
50c0193
Merge remote-tracking branch 'origin/json-api-resource' into json-api…
crynobone Oct 30, 2025
2b69984
wip
crynobone Oct 30, 2025
b006401
Apply fixes from StyleCI
StyleCIBot Oct 30, 2025
174b4a8
wip
crynobone Oct 30, 2025
13fedeb
Apply fixes from StyleCI
StyleCIBot Oct 30, 2025
5c15920
wip
crynobone Oct 30, 2025
0319cbe
wip
crynobone Oct 30, 2025
a3ee8f7
wip
crynobone Oct 30, 2025
b610d9c
wip
crynobone Oct 30, 2025
b1c0b2a
Apply fixes from StyleCI
StyleCIBot Oct 30, 2025
e7a8d6e
wip
crynobone Oct 30, 2025
f153b5e
Apply fixes from StyleCI
StyleCIBot Oct 30, 2025
dab4d40
wip
crynobone Oct 30, 2025
c742be0
wip
crynobone Oct 30, 2025
1fc4aaa
Merge remote-tracking branch 'origin/json-api-resource' into json-api…
crynobone Oct 30, 2025
bc8e87a
wip
crynobone Oct 30, 2025
99bf9a6
wip
crynobone Oct 30, 2025
f9bfd62
wip
crynobone Oct 30, 2025
62c56c0
Apply fixes from StyleCI
StyleCIBot Oct 30, 2025
e9c68b0
wip
crynobone Oct 30, 2025
f0f58d9
wip
crynobone Oct 30, 2025
e1212fb
Apply fixes from StyleCI
StyleCIBot Oct 30, 2025
1928b74
wip
crynobone Oct 30, 2025
4e27c4b
wip
crynobone Oct 30, 2025
387e2a4
wip
crynobone Oct 30, 2025
73c243a
wip
crynobone Oct 30, 2025
ab05c9f
wip
crynobone Oct 30, 2025
d8ecdbc
wip
crynobone Oct 30, 2025
9ce5b07
Apply fixes from StyleCI
StyleCIBot Oct 30, 2025
e1f0bbd
wip
crynobone Oct 30, 2025
5b3f81c
wip
crynobone Oct 30, 2025
eda7c76
wip
crynobone Oct 30, 2025
9b279bb
Apply suggestions from code review
crynobone Oct 30, 2025
6275377
wip
crynobone Oct 30, 2025
280c18c
wip
crynobone Oct 30, 2025
ac0ec25
wip
crynobone Oct 30, 2025
f466566
Apply fixes from StyleCI
StyleCIBot Oct 30, 2025
d45e57b
wip
crynobone Oct 30, 2025
dc0ec65
wip
crynobone Oct 30, 2025
f4bf030
wip
crynobone Oct 30, 2025
e5c2f88
Apply fixes from StyleCI
StyleCIBot Oct 30, 2025
4a8cfc2
wip
crynobone Oct 30, 2025
8f9d151
Apply fixes from StyleCI
StyleCIBot Oct 30, 2025
76cc84e
wip
crynobone Oct 30, 2025
86884a9
Apply fixes from StyleCI
StyleCIBot Oct 30, 2025
afb51d1
wip
crynobone Oct 30, 2025
5f52c26
Apply fixes from StyleCI
StyleCIBot Oct 30, 2025
4284619
wip
crynobone Oct 30, 2025
504193d
Apply fixes from StyleCI
StyleCIBot Oct 30, 2025
1a51b54
wip
crynobone Oct 30, 2025
0ed469a
wip
crynobone Oct 30, 2025
a17ac8d
remove asJsonApi from base resource
taylorotwell Oct 30, 2025
6836018
update exception
taylorotwell Oct 30, 2025
5459428
formatting
taylorotwell Oct 30, 2025
4a5e360
fix test
taylorotwell Oct 30, 2025
215b9ba
formatting
taylorotwell Oct 30, 2025
573a57a
formatting
taylorotwell Oct 30, 2025
115ed94
formatting
taylorotwell Oct 30, 2025
1da745b
rename trait
taylorotwell Oct 30, 2025
8e20f20
Merge remote-tracking branch 'origin/12.x' into json-api-resource
crynobone Oct 31, 2025
4abf43a
[JSON:API] Add `toAttributes()` method (#57603)
crynobone Oct 31, 2025
4451594
[JSON:API] Allows `JsonApiResource::$attributes` (#57638)
crynobone Nov 3, 2025
be536df
[JSON:API] Supports `JsonApiResource::toRelationships()` (#57646)
crynobone Nov 7, 2025
ea1ea07
formatting
taylorotwell 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
9 changes: 6 additions & 3 deletions src/Illuminate/Foundation/Console/ResourceMakeCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,11 @@ public function handle()
*/
protected function getStub()
{
return $this->collection()
? $this->resolveStubPath('/stubs/resource-collection.stub')
: $this->resolveStubPath('/stubs/resource.stub');
return match (true) {
$this->collection() => $this->resolveStubPath('/stubs/resource-collection.stub'),
$this->option('json-api') => $this->resolveStubPath('/stubs/resource-json-api.stub'),
default => $this->resolveStubPath('/stubs/resource.stub'),
};
}

/**
Expand Down Expand Up @@ -100,6 +102,7 @@ protected function getOptions()
{
return [
['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the resource already exists'],
['json-api', 'j', InputOption::VALUE_NONE, 'Create a JSON:API resource'],
['collection', 'c', InputOption::VALUE_NONE, 'Create a resource collection'],
];
}
Expand Down
23 changes: 23 additions & 0 deletions src/Illuminate/Foundation/Console/stubs/resource-json-api.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace {{ namespace }};

use Illuminate\Http\Request;
use Illuminate\Http\Resources\JsonApi\JsonApiResource;

class {{ class }} extends JsonApiResource
{
/**
* The resource's attributes.
*/
public $attributes = [
// ...
];

/**
* The resource's relationships.
*/
public $relationships = [
// ...
];
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Http\Middleware\TrustHosts;
use Illuminate\Http\Middleware\TrustProxies;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Http\Resources\JsonApi\JsonApiResource;
use Illuminate\Mail\Markdown;
use Illuminate\Queue\Console\WorkCommand;
use Illuminate\Queue\Queue;
Expand Down Expand Up @@ -177,6 +179,8 @@ protected function tearDownTheTestEnvironment(): void
EncodedHtmlString::flushState();
EncryptCookies::flushState();
HandleExceptions::flushState($this);
JsonApiResource::flushState();
JsonResource::flushState();
Markdown::flushState();
Migrator::withoutMigrations([]);
Once::flush();
Expand Down
40 changes: 36 additions & 4 deletions src/Illuminate/Http/Resources/Json/JsonResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ protected static function newCollection($resource)
*/
public function resolve($request = null)
{
$data = $this->toArray(
$request ?: Container::getInstance()->make('request')
$data = $this->toAttributes(
$request ?: $this->resolveRequestFromContainer()
);

if ($data instanceof Arrayable) {
Expand All @@ -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.
*
Expand Down Expand Up @@ -219,6 +230,16 @@ public function withResponse(Request $request, JsonResponse $response)
//
}

/**
* Resolve the HTTP request instance from container.
*
* @return \Illuminate\Http\Request
*/
protected function resolveRequestFromContainer()
{
return Container::getInstance()->make('request');
}

/**
* Set the string that should wrap the outer-most resource array.
*
Expand Down Expand Up @@ -249,7 +270,7 @@ public static function withoutWrapping()
public function response($request = null)
{
return $this->toResponse(
$request ?: Container::getInstance()->make('request')
$request ?: $this->resolveRequestFromContainer()
);
}

Expand All @@ -271,6 +292,17 @@ public function toResponse($request)
*/
public function jsonSerialize(): array
{
return $this->resolve(Container::getInstance()->make('request'));
return $this->resolve($this->resolveRequestFromContainer());
}

/**
* Flush the resource's global state.
*
* @return void
*/
public static function flushState()
{
static::$wrap = 'data';
static::$forceWrapping = false;
}
}
4 changes: 2 additions & 2 deletions src/Illuminate/Http/Resources/Json/ResourceCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php

namespace Illuminate\Http\Resources\JsonApi;

use Illuminate\Container\Container;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class AnonymousResourceCollection extends \Illuminate\Http\Resources\Json\AnonymousResourceCollection
{
use Concerns\ResolvesJsonApiRequest;

/**
* Get any additional data that should be returned with the resource array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
#[\Override]
public function with($request)
{
return array_filter([
'included' => $this->collection
->map(fn ($resource) => $resource->resolveIncludedResources($request))
->flatten(depth: 1)
->all(),
...($implementation = JsonApiResource::$jsonApiInformation)
? ['jsonapi' => $implementation]
: [],
]);
}

/**
* Transform the resource into a JSON array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
#[\Override]
public function toAttributes(Request $request)
{
return $this->collection
->map(fn ($resource) => $resource->resolveResourceData($request))
->all();
}

/**
* Customize the outgoing response for the resource.
*
* @param \Illuminate\Http\Request $request
* @param \Illuminate\Http\JsonResponse $response
* @return void
*/
#[\Override]
public function withResponse(Request $request, JsonResponse $response): void
{
$response->header('Content-Type', 'application/vnd.api+json');
}

/**
* Create an HTTP response that represents the object.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
#[\Override]
public function toResponse($request)
{
return parent::toResponse($this->resolveJsonApiRequestFrom($request));
}

/**
* Resolve the HTTP request instance from container.
*
* @return \Illuminate\Http\Resources\JsonApi\SparseRequest
*/
#[\Override]
protected function resolveRequestFromContainer()
{
return $this->resolveJsonApiRequestFrom(Container::getInstance()->make('request'));
}
}
Loading