Skip to content

Commit 93e5ea6

Browse files
[9.x] Throw exception when ResourceCollection collects something else than … (#40844)
* Throw exception when ResourceCollection collects something else than JsonResource * Apply StyleCI * Throw LogicException instead of RuntimeException * formatting Co-authored-by: Taylor Otwell <[email protected]>
1 parent 44a7582 commit 93e5ea6

File tree

3 files changed

+43
-5
lines changed

3 files changed

+43
-5
lines changed

src/Illuminate/Http/Resources/CollectsResources.php

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22

33
namespace Illuminate\Http\Resources;
44

5+
use Illuminate\Http\Resources\Json\JsonResource;
56
use Illuminate\Pagination\AbstractCursorPaginator;
67
use Illuminate\Pagination\AbstractPaginator;
78
use Illuminate\Support\Collection;
89
use Illuminate\Support\Str;
10+
use LogicException;
911
use ReflectionClass;
1012
use Traversable;
1113

@@ -45,15 +47,21 @@ protected function collectResource($resource)
4547
*/
4648
protected function collects()
4749
{
48-
if ($this->collects) {
49-
return $this->collects;
50-
}
50+
$collects = null;
5151

52-
if (str_ends_with(class_basename($this), 'Collection') &&
52+
if ($this->collects) {
53+
$collects = $this->collects;
54+
} elseif (str_ends_with(class_basename($this), 'Collection') &&
5355
(class_exists($class = Str::replaceLast('Collection', '', get_class($this))) ||
5456
class_exists($class = Str::replaceLast('Collection', 'Resource', get_class($this))))) {
55-
return $class;
57+
$collects = $class;
5658
}
59+
60+
if (! $collects || is_subclass_of($collects, JsonResource::class)) {
61+
return $collects;
62+
}
63+
64+
throw new LogicException('Resource collections must collect instances of '.JsonResource::class.'.');
5765
}
5866

5967
/**
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace Illuminate\Tests\Integration\Http\Fixtures;
4+
5+
use Illuminate\Http\Resources\Json\ResourceCollection;
6+
7+
class PostModelCollectionResource extends ResourceCollection
8+
{
9+
public $collects = Post::class;
10+
11+
public function toArray($request)
12+
{
13+
return ['data' => $this->collection];
14+
}
15+
}

tests/Integration/Http/ResourceTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use Illuminate\Tests\Integration\Http\Fixtures\Post;
2222
use Illuminate\Tests\Integration\Http\Fixtures\PostCollectionResource;
2323
use Illuminate\Tests\Integration\Http\Fixtures\PostCollectionResourceWithPaginationInformation;
24+
use Illuminate\Tests\Integration\Http\Fixtures\PostModelCollectionResource;
2425
use Illuminate\Tests\Integration\Http\Fixtures\PostResource;
2526
use Illuminate\Tests\Integration\Http\Fixtures\PostResourceWithAnonymousResourceCollectionWithPaginationInformation;
2627
use Illuminate\Tests\Integration\Http\Fixtures\PostResourceWithExtraData;
@@ -36,6 +37,7 @@
3637
use Illuminate\Tests\Integration\Http\Fixtures\ResourceWithPreservedKeys;
3738
use Illuminate\Tests\Integration\Http\Fixtures\SerializablePostResource;
3839
use Illuminate\Tests\Integration\Http\Fixtures\Subscription;
40+
use LogicException;
3941
use Mockery;
4042
use Orchestra\Testbench\TestCase;
4143

@@ -1043,6 +1045,19 @@ public function testCollectionResourcesAreCountable()
10431045
$this->assertCount(2, $collection);
10441046
}
10451047

1048+
public function testCollectionResourcesMustCollectResources()
1049+
{
1050+
$posts = collect([
1051+
new Post(['id' => 1, 'title' => 'Test title']),
1052+
new Post(['id' => 2, 'title' => 'Test title 2']),
1053+
]);
1054+
1055+
$this->expectException(LogicException::class);
1056+
$this->expectExceptionMessage('must collect');
1057+
1058+
new PostModelCollectionResource($posts);
1059+
}
1060+
10461061
public function testKeysArePreservedIfTheResourceIsFlaggedToPreserveKeys()
10471062
{
10481063
$data = [

0 commit comments

Comments
 (0)