PHP native Enum type not supported
davidmohamedfr opened this issue · 9 comments
Hi !
I'm having a "Path cannot be empty" error on docs generation because i'm using native Enum class from PHP
From what I've investigate, trouble come from MethodReflector:getReflection
using new ReflectionMethod
when reflection for Enum need to be used with new ReflectionEnum
Hope this will help someone fix this issue.
@davidmohamedfr please share some code examples so I can reproduce
This is an example.
I'm in PHP 8.3.2, using Laravel Framework 11.2.0 and Scramble 0.10.13
enum MyEnum: int
{
case TITI = 1;
case TOTO = 2;
public function label(): string
{
return match ($this) {
Origin::TITI => 'titi',
Origin::TOTO => 'toto',
};
}
}
enum CarsEnum: int
{
case TOYOTA= 1;
case FERRARI = 2;
}
/**
* @param array<string, mixed> $data
*/
public static function create(array $data)
{
return new DTO(
titi: MyEnum::from($data['titi']),
cars: CarsEnum::from($data['cars']),
);
}
@davidmohamedfr I still don't understand how your controller looks like for the api route that fails
@davidmohamedfr Please share the code that I can use to reproduce. This includes everything that is needed to have the same issue
Hello. Yes, the issue is present.
Code for reproducing:
Enum:
<?php
enum SupplierGroupEnum: int
{
case TEST = 1;
}
Controller:
<?php
final class SupplierGroupController extends Controller
{
public function index(): JsonResource
{
$supplierGroups = SupplierGroupEnum::cases();
return EnumResource::collection($supplierGroups);
}
}
Additionally, this issue appears after version 0.10.11.
@Tegos I still cannot reproduce the error. I can confirm the type of Enum::cases()
is not inferred, but there is no error (exception)
Hm, ok, let's try to check again :)
PHP: 8.1
Composer: "dedoc/scramble": "v0.10.13"
Controller:
<?php
namespace App\Http\Controllers\Api\Static;
use App\Http\Controllers\Controller;
use App\Http\Resources\System\EnumResource;
use App\Support\Enums\Supplier\SupplierDeliveryType;
use Illuminate\Http\Resources\Json\JsonResource;
final class SupplierDeliveryTypeController extends Controller
{
public function index(): JsonResource
{
$supplierDeliveryTypes = SupplierDeliveryType::cases();
return EnumResource::collection($supplierDeliveryTypes);
}
}
Enum:
<?php
namespace App\Support\Enums\Supplier;
use App\Support\Enums\Interfaces\LabelableEnum;
enum SupplierDeliveryType: int implements LabelableEnum
{
case LOCAL = 0;
case PLANE = 1;
case SHIP = 2;
case TRUCK = 3;
public function label(): string
{
return SupplierDeliveryType::getLabel($this);
}
public static function getLabel(self $value): string
{
return match ($value) {
SupplierDeliveryType::LOCAL => 'Немає',
SupplierDeliveryType::PLANE => 'Авіа',
SupplierDeliveryType::SHIP => 'Море',
SupplierDeliveryType::TRUCK => 'Авто',
};
}
}
Resource:
<?php
namespace App\Http\Resources\System;
use App\Support\Enums\Interfaces\LabelableEnum;
use BackedEnum;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
final class EnumResource extends JsonResource
{
public function toArray(Request $request): array
{
/** @var BackedEnum|LabelableEnum $enumUnit */
$enumUnit = $this->resource;
return [
'id' => $enumUnit->value,
'slug' => $enumUnit->name,
'name' => $enumUnit->label(),
];
}
}
stacktrace
[2024-07-07 20:50:25] local.ERROR: Error when analyzing route 'GET api/admin/static/supplier-delivery-types' (App\Http\Controllers\Api\Static\SupplierDeliveryTypeController@index): Path cannot be empty – vendor\dedoc\scramble\src\Infer\Reflector\MethodReflector.php on line 40
[2024-07-07 20:50:25] local.ERROR: Path cannot be empty {"exception":"[object] (ValueError(code: 0): Path cannot be empty at \\vendor\\dedoc\\scramble\\src\\Infer\\Reflector\\MethodReflector.php:40)
[stacktrace]
#0 \\vendor\\dedoc\\scramble\\src\\Infer\\Reflector\\MethodReflector.php(40): file_get_contents()
#1 \\vendor\\dedoc\\scramble\\src\\Infer\\Reflector\\MethodReflector.php(60): Dedoc\\Scramble\\Infer\\Reflector\\MethodReflector->getMethodCode()
#2 \\vendor\\dedoc\\scramble\\src\\Infer\\Analyzer\\MethodAnalyzer.php(32): Dedoc\\Scramble\\Infer\\Reflector\\MethodReflector->getAstNode()
#3 \\vendor\\dedoc\\scramble\\src\\Infer\\Definition\\ClassDefinition.php(63): Dedoc\\Scramble\\Infer\\Analyzer\\MethodAnalyzer->analyze()
#4 \\vendor\\dedoc\\scramble\\src\\Infer\\Services\\ReferenceTypeResolver.php(264): Dedoc\\Scramble\\Infer\\Definition\\ClassDefinition->getMethodDefinition()
#5 \\vendor\\dedoc\\scramble\\src\\Infer\\Services\\ReferenceTypeResolver.php(131): Dedoc\\Scramble\\Infer\\Services\\ReferenceTypeResolver->resolveStaticMethodCallReferenceType()
#6 \\vendor\\dedoc\\scramble\\src\\Infer\\Services\\ReferenceTypeResolver.php(149): Dedoc\\Scramble\\Infer\\Services\\ReferenceTypeResolver->Dedoc\\Scramble\\Infer\\Services\\{closure}()
#7 \\vendor\\dedoc\\scramble\\src\\Infer\\Services\\ReferenceTypeResolver.php(72): Dedoc\\Scramble\\Infer\\Services\\ReferenceTypeResolver->doResolve()
#8 \\vendor\\dedoc\\scramble\\src\\Support\\Type\\TypeWalker.php(33): Dedoc\\Scramble\\Infer\\Services\\ReferenceTypeResolver->Dedoc\\Scramble\\Infer\\Services\\{closure}()
#9 \\vendor\\dedoc\\scramble\\src\\Support\\Type\\TypeWalker.php(50): Dedoc\\Scramble\\Support\\Type\\TypeWalker->replace()
#10 \\vendor\\dedoc\\scramble\\src\\Support\\Type\\TypeWalker.php(50): Dedoc\\Scramble\\Support\\Type\\TypeWalker->replace()
#11 \\vendor\\dedoc\\scramble\\src\\Infer\\Services\\ReferenceTypeResolver.php(72): Dedoc\\Scramble\\Support\\Type\\TypeWalker->replace()
#12 \\vendor\\dedoc\\scramble\\src\\Infer\\Services\\RecursionGuard.php(35): Dedoc\\Scramble\\Infer\\Services\\ReferenceTypeResolver->Dedoc\\Scramble\\Infer\\Services\\{closure}()
#13 \\vendor\\dedoc\\scramble\\src\\Infer\\Services\\ReferenceTypeResolver.php(74): Dedoc\\Scramble\\Infer\\Services\\RecursionGuard::run()
#14 \\vendor\\dedoc\\scramble\\src\\Infer\\Definition\\ClassDefinition.php(76): Dedoc\\Scramble\\Infer\\Services\\ReferenceTypeResolver->resolve()
#15 \\vendor\\dedoc\\scramble\\src\\Support\\RouteInfo.php(233): Dedoc\\Scramble\\Infer\\Definition\\ClassDefinition->getMethodDefinition()
#16 \\vendor\\dedoc\\scramble\\src\\Support\\OperationExtensions\\RequestBodyExtension.php(33): Dedoc\\Scramble\\Support\\RouteInfo->getMethodType()
#17 \\vendor\\dedoc\\scramble\\src\\Support\\OperationBuilder.php(28): Dedoc\\Scramble\\Support\\OperationExtensions\\RequestBodyExtension->handle()
#18 \\vendor\\dedoc\\scramble\\src\\Generator.php(142): Dedoc\\Scramble\\Support\\OperationBuilder->build()
#19 \\vendor\\dedoc\\scramble\\src\\Generator.php(44): Dedoc\\Scramble\\Generator->routeToOperation()
#20 [internal function]: Dedoc\\Scramble\\Generator->Dedoc\\Scramble\\{closure}()
#21 \\vendor\\laravel\\framework\\src\\Illuminate\\Collections\\Arr.php(600): array_map()
#22 \\vendor\\laravel\\framework\\src\\Illuminate\\Collections\\Collection.php(778): Illuminate\\Support\\Arr::map()
#23 \\vendor\\dedoc\\scramble\\src\\Generator.php(56): Illuminate\\Support\\Collection->map()
#24 \\vendor\\dedoc\\scramble\\src\\Scramble.php(123): Dedoc\\Scramble\\Generator->__invoke()
#25 \\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\CallableDispatcher.php(40): Dedoc\\Scramble\\Scramble::Dedoc\\Scramble\\{closure}()
#26 \\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Route.php(237): Illuminate\\Routing\\CallableDispatcher->dispatch()
#27 \\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Route.php(208): Illuminate\\Routing\\Route->runCallable()
#28 \\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php(806): Illuminate\\Routing\\Route->run()
#29 \\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(144): Illuminate\\Routing\\Router->Illuminate\\Routing\\{closure}()
#30 \\app\\Http\\Middleware\\HttpBasicAuth.php(28): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#31 \\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(183): App\\Http\\Middleware\\HttpBasicAuth->handle()
#32 \\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\VerifyCsrfToken.php(78): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#33 \\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(183): Illuminate\\Foundation\\Http\\Middleware\\VerifyCsrfToken->handle()
#34 \\vendor\\laravel\\framework\\src\\Illuminate\\Session\\Middleware\\StartSession.php(121): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#35 \\vendor\\laravel\\framework\\src\\Illuminate\\Session\\Middleware\\StartSession.php(64): Illuminate\\Session\\Middleware\\StartSession->handleStatefulRequest()
#36 \\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(183): Illuminate\\Session\\Middleware\\StartSession->handle()
#37 \\vendor\\laravel\\framework\\src\\Illuminate\\Cookie\\Middleware\\EncryptCookies.php(67): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#38 \\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(183): Illuminate\\Cookie\\Middleware\\EncryptCookies->handle()
#39 \\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(119): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#40 \\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php(807): Illuminate\\Pipeline\\Pipeline->then()
#41 \\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php(784): Illuminate\\Routing\\Router->runRouteWithinStack()
#42 \\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php(748): Illuminate\\Routing\\Router->runRoute()
#43 \\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\Router.php(737): Illuminate\\Routing\\Router->dispatchToRoute()
#44 \\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Kernel.php(200): Illuminate\\Routing\\Router->dispatch()
#45 \\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(144): Illuminate\\Foundation\\Http\\Kernel->Illuminate\\Foundation\\Http\\{closure}()
#46 \\app\\Http\\Middleware\\ForceJsonResponse.php(13): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#47 \\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(183): App\\Http\\Middleware\\ForceJsonResponse->handle()
#48 \\app\\Http\\Middleware\\SentryContext.php(49): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#49 \\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(183): App\\Http\\Middleware\\SentryContext->handle()
#50 \\vendor\\hryha\\request-logger\\src\\Http\\Middleware\\RequestLogger.php(25): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#51 \\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(183): Hryha\\RequestLogger\\Http\\Middleware\\RequestLogger->handle()
#52 \\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#53 \\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\ConvertEmptyStringsToNull.php(31): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle()
#54 \\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(183): Illuminate\\Foundation\\Http\\Middleware\\ConvertEmptyStringsToNull->handle()
#55 \\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest.php(21): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#56 \\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\TrimStrings.php(40): Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest->handle()
#57 \\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(183): Illuminate\\Foundation\\Http\\Middleware\\TrimStrings->handle()
#58 \\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize.php(27): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#59 \\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(183): Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize->handle()
#60 \\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance.php(99): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#61 \\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(183): Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance->handle()
#62 \\vendor\\laravel\\framework\\src\\Illuminate\\Http\\Middleware\\HandleCors.php(49): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#63 \\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(183): Illuminate\\Http\\Middleware\\HandleCors->handle()
#64 \\vendor\\laravel\\framework\\src\\Illuminate\\Http\\Middleware\\TrustProxies.php(39): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#65 \\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(183): Illuminate\\Http\\Middleware\\TrustProxies->handle()
#66 \\vendor\\itsgoingd\\clockwork\\Clockwork\\Support\\Laravel\\ClockworkMiddleware.php(24): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#67 \\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(183): Clockwork\\Support\\Laravel\\ClockworkMiddleware->handle()
#68 \\vendor\\laravel\\framework\\src\\Illuminate\\Pipeline\\Pipeline.php(119): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()
#69 \\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Kernel.php(175): Illuminate\\Pipeline\\Pipeline->then()
#70 \\vendor\\laravel\\framework\\src\\Illuminate\\Foundation\\Http\\Kernel.php(144): Illuminate\\Foundation\\Http\\Kernel->sendRequestThroughRouter()
#71 \\public\\index.php(52): Illuminate\\Foundation\\Http\\Kernel->handle()
#72 {main}
"}
@Tegos reproduced on 0.10.13
!
Fixed in 0.11.*
!
Closing the issue as not reproducible in 0.11.*
. Feel free to re-open if it is reproduced in 0.11.*