From a1a54e33e569c487b4a5d425aef38ceba8fc5beb Mon Sep 17 00:00:00 2001 From: Martin Kluska Date: Fri, 2 Aug 2024 16:44:04 +0200 Subject: [PATCH] feat(PHPStan): Provide @template for JsonResource $resource for better type safe BREAKING CHANGE: PHPStan will now throw an error if you pass incorrect value to __construct or Resource::collection - made setContainer/getContainer/resourceArray/instance final --- phpstan-baseline.neon | 2 +- src/Http/Resources/JsonResource.php | 30 ++++++++++++++++--- src/Http/Resources/MessageResource.php | 7 +---- .../Http/Resources/LaraStrictResource.php | 7 +---- .../Http/Resources/ResourceArrayResource.php | 7 +---- 5 files changed, 30 insertions(+), 23 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 31b175fb..472c0387 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,7 +1,7 @@ parameters: ignoreErrors: - - message: "#^Access to an undefined property LaraStrict\\\\Http\\\\Resources\\\\JsonResource\\:\\:\\$preserveKeys\\.$#" + message: "#^Access to an undefined property LaraStrict\\\\Http\\\\Resources\\\\JsonResource\\\\:\\:\\$preserveKeys\\.$#" count: 1 path: src/Http/Resources/JsonResource.php diff --git a/src/Http/Resources/JsonResource.php b/src/Http/Resources/JsonResource.php index 939661d5..815c6f24 100644 --- a/src/Http/Resources/JsonResource.php +++ b/src/Http/Resources/JsonResource.php @@ -6,20 +6,42 @@ use Illuminate\Container\Container as LaravelContainer; use Illuminate\Contracts\Container\Container; +use Illuminate\Contracts\Pagination\Paginator; +use Illuminate\Database\Eloquent\Collection; use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\JsonResource as BaseJsonResource; +use Illuminate\Pagination\AbstractPaginator; +use Illuminate\Support\Collection as SupportCollection; +/** + * @template TResource + * + * @property TResource $resource + */ abstract class JsonResource extends BaseJsonResource { private ?Container $container = null; - public function setContainer(Container $container): self + /** + * When created in your code base, it non-null, but Laravel for "collection" uses null. + * + * @param TResource $resource + */ + public function __construct($resource) + { + parent::__construct($resource); + } + + final public function setContainer(Container $container): static { $this->container = $container; return $this; } + /** + * @param array|Collection|SupportCollection|Paginator|AbstractPaginator $resource + */ public static function collection($resource): JsonResourceCollection { return tap( @@ -34,7 +56,7 @@ static function (JsonResourceCollection $collection) { ); } - protected function getContainer(): Container + final protected function getContainer(): Container { if ($this->container === null) { return LaravelContainer::getInstance(); @@ -49,7 +71,7 @@ protected function getContainer(): Container * * @return array */ - protected function resourceArray(Request $request, BaseJsonResource $resource): array + final protected function resourceArray(Request $request, BaseJsonResource $resource): array { if ($resource instanceof self || $resource instanceof JsonResourceCollection) { $resource->setContainer($this->getContainer()); @@ -66,7 +88,7 @@ protected function resourceArray(Request $request, BaseJsonResource $resource): * * @return TInstance */ - protected function instance(string $class, array $parameters = []): object + final protected function instance(string $class, array $parameters = []): object { return $this ->getContainer() diff --git a/src/Http/Resources/MessageResource.php b/src/Http/Resources/MessageResource.php index 769fec2d..27440cb5 100644 --- a/src/Http/Resources/MessageResource.php +++ b/src/Http/Resources/MessageResource.php @@ -7,17 +7,12 @@ use LaraStrict\Http\Enums\HttpMessage; /** - * @property HttpMessage|string $resource + * @extends JsonResource */ class MessageResource extends JsonResource { public static $wrap = null; - public function __construct(HttpMessage|string|null $resource) - { - parent::__construct($resource); - } - /** * @return array */ diff --git a/tests/Feature/Http/Resources/LaraStrictResource.php b/tests/Feature/Http/Resources/LaraStrictResource.php index 52bac459..d09fd58c 100644 --- a/tests/Feature/Http/Resources/LaraStrictResource.php +++ b/tests/Feature/Http/Resources/LaraStrictResource.php @@ -7,15 +7,10 @@ use LaraStrict\Http\Resources\JsonResource; /** - * @property TestEntity $resource + * @extends JsonResource */ class LaraStrictResource extends JsonResource { - public function __construct(?TestEntity $resource) - { - parent::__construct($resource); - } - public function toArray($request): array { return [ diff --git a/tests/Unit/Http/Resources/ResourceArrayResource.php b/tests/Unit/Http/Resources/ResourceArrayResource.php index be386302..a54e37d4 100644 --- a/tests/Unit/Http/Resources/ResourceArrayResource.php +++ b/tests/Unit/Http/Resources/ResourceArrayResource.php @@ -8,15 +8,10 @@ use LaraStrict\Http\Resources\JsonResource; /** - * @property BaseJsonResource $resource + * @extends JsonResource */ class ResourceArrayResource extends JsonResource { - public function __construct(?BaseJsonResource $resource) - { - parent::__construct($resource); - } - /** * @return array>> */