Skip to content

Commit 424f97a

Browse files
[8.x] Avoid constructor call when fetching resource JSON options (#40261)
* Avoid constructor call when fetching json options * Update CollectsResources.php * Update CollectsResources.php Co-authored-by: Taylor Otwell <[email protected]>
1 parent 8c293f9 commit 424f97a

File tree

3 files changed

+56
-1
lines changed

3 files changed

+56
-1
lines changed

src/Illuminate/Http/Resources/CollectsResources.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Illuminate\Pagination\AbstractPaginator;
77
use Illuminate\Support\Collection;
88
use Illuminate\Support\Str;
9+
use ReflectionClass;
910

1011
trait CollectsResources
1112
{
@@ -63,7 +64,13 @@ public function jsonOptions()
6364
{
6465
$collects = $this->collects();
6566

66-
return $collects ? (new $collects([]))->jsonOptions() : 0;
67+
if (! $collects) {
68+
return 0;
69+
}
70+
71+
return (new ReflectionClass($collects))
72+
->newInstanceWithoutConstructor()
73+
->jsonOptions();
6774
}
6875

6976
/**
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace Illuminate\Tests\Integration\Http\Fixtures;
4+
5+
use Illuminate\Http\Resources\Json\JsonResource;
6+
7+
class PostResourceWithJsonOptionsAndTypeHints extends JsonResource
8+
{
9+
public function __construct(Post $resource)
10+
{
11+
parent::__construct($resource);
12+
}
13+
14+
public function toArray($request)
15+
{
16+
return [
17+
'id' => $this->id,
18+
'title' => $this->title,
19+
'reading_time' => $this->reading_time,
20+
];
21+
}
22+
23+
public function jsonOptions()
24+
{
25+
return JSON_PRESERVE_ZERO_FRACTION;
26+
}
27+
}

tests/Integration/Http/ResourceTest.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
use Illuminate\Tests\Integration\Http\Fixtures\PostResourceWithAnonymousResourceCollectionWithPaginationInformation;
2626
use Illuminate\Tests\Integration\Http\Fixtures\PostResourceWithExtraData;
2727
use Illuminate\Tests\Integration\Http\Fixtures\PostResourceWithJsonOptions;
28+
use Illuminate\Tests\Integration\Http\Fixtures\PostResourceWithJsonOptionsAndTypeHints;
2829
use Illuminate\Tests\Integration\Http\Fixtures\PostResourceWithOptionalAppendedAttributes;
2930
use Illuminate\Tests\Integration\Http\Fixtures\PostResourceWithOptionalData;
3031
use Illuminate\Tests\Integration\Http\Fixtures\PostResourceWithOptionalMerging;
@@ -555,6 +556,26 @@ public function testResourcesMayCustomizeJsonOptionsOnPaginatedResponse()
555556
);
556557
}
557558

559+
public function testResourcesMayCustomizeJsonOptionsWithTypeHintedConstructor()
560+
{
561+
Route::get('/', function () {
562+
return new PostResourceWithJsonOptionsAndTypeHints(new Post([
563+
'id' => 5,
564+
'title' => 'Test Title',
565+
'reading_time' => 3.0,
566+
]));
567+
});
568+
569+
$response = $this->withoutExceptionHandling()->get(
570+
'/', ['Accept' => 'application/json']
571+
);
572+
573+
$this->assertEquals(
574+
'{"data":{"id":5,"title":"Test Title","reading_time":3.0}}',
575+
$response->baseResponse->content()
576+
);
577+
}
578+
558579
public function testCustomHeadersMayBeSetOnResponses()
559580
{
560581
Route::get('/', function () {

0 commit comments

Comments
 (0)