knuckleswtf / scribe

Generate API documentation for humans from your Laravel codebase.✍
https://scribe.knuckles.wtf/laravel/
MIT License
1.72k stars 307 forks source link

Reflection Exception #115

Closed AliAlican closed 3 years ago

AliAlican commented 4 years ago

Php artisan scribe:generate doesn't work I'm getting this error image

Screenshots and stack traces: With Verbose � info Processed route: [GET] _debugbar/open � info Processed route: [GET] _debugbar/clockwork/{id} � info Processed route: [GET] _debugbar/telescope/{id} � info Processed route: [GET] _debugbar/assets/stylesheets � info Processed route: [GET] _debugbar/assets/javascript � info Processed route: [DELETE] _debugbar/cache/{key}/{tags?}

ReflectionException

Class C:32:"Opis\Closure\SerializableClosure":251:{ does not exist

at vendor/knuckleswtf/scribe/src/Commands/GenerateDocumentation.php:157 153▕ */ 154▕ private function doesControllerMethodExist(array $routeControllerAndMethod) 155▕ { 156▕ [$class, $method] = $routeControllerAndMethod; ➜ 157▕ $reflection = new ReflectionClass($class); 158▕ 159▕ if ($reflection->hasMethod($method)) { 160▕ return true; 161▕ }

1 vendor/knuckleswtf/scribe/src/Commands/GenerateDocumentation.php:157 ReflectionClass::__construct("C:32:"Opis\Closure\SerializableClosure":251:{")

2 vendor/knuckleswtf/scribe/src/Commands/GenerateDocumentation.php:107 Knuckles\Scribe\Commands\GenerateDocumentation::doesControllerMethodExist()

3 vendor/knuckleswtf/scribe/src/Commands/GenerateDocumentation.php:73 Knuckles\Scribe\Commands\GenerateDocumentation::processRoutes()

4 vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:37 Knuckles\Scribe\Commands\GenerateDocumentation::handle(Object(Knuckles\Scribe\Matching\RouteMatcher))

5 vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:37 call_user_func_array()

6 vendor/laravel/framework/src/Illuminate/Container/Util.php:40 Illuminate\Container\BoundMethod::Illuminate\Container{closure}()

7 vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:95 Illuminate\Container\Util::unwrapIfClosure(Object(Closure))

8 vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:39 Illuminate\Container\BoundMethod::callBoundMethod(Object(Illuminate\Foundation\Application), Object(Closure))

9 vendor/laravel/framework/src/Illuminate/Container/Container.php:596 Illuminate\Container\BoundMethod::call(Object(Illuminate\Foundation\Application), [])

10 vendor/laravel/framework/src/Illuminate/Console/Command.php:136 Illuminate\Container\Container::call()

11 vendor/symfony/console/Command/Command.php:258 Illuminate\Console\Command::execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Illuminate\Console\OutputStyle))

12 vendor/laravel/framework/src/Illuminate/Console/Command.php:121 Symfony\Component\Console\Command\Command::run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Illuminate\Console\OutputStyle))

13 vendor/symfony/console/Application.php:920 Illuminate\Console\Command::run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))

14 vendor/symfony/console/Application.php:266 Symfony\Component\Console\Application::doRunCommand(Object(Knuckles\Scribe\Commands\GenerateDocumentation), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))

15 vendor/symfony/console/Application.php:142 Symfony\Component\Console\Application::doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))

16 vendor/laravel/framework/src/Illuminate/Console/Application.php:93 Symfony\Component\Console\Application::run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))

17 vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php:129 Illuminate\Console\Application::run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))

18 artisan:35 Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))

My environment:

autoload files psr-4 Illuminate\ => src/Illuminate/ Illuminate\Support\ => src/Illuminate/Macroable/, src/Illuminate/Collections/

requires doctrine/inflector ^1.4|^2.0 dragonmantank/cron-expression ^3.0 egulias/email-validator ^2.1.10 ext-json ext-mbstring ext-openssl * league/commonmark ^1.3 league/flysystem ^1.0.34 monolog/monolog ^2.0 nesbot/carbon ^2.17 opis/closure ^3.5.3 php ^7.3 psr/container ^1.0 psr/simple-cache ^1.0 ramsey/uuid ^4.0 swiftmailer/swiftmailer ^6.0 symfony/console ^5.1 symfony/error-handler ^5.1 symfony/finder ^5.1 symfony/http-foundation ^5.1 symfony/http-kernel ^5.1 symfony/mime ^5.1 symfony/process ^5.1 symfony/routing ^5.1 symfony/var-dumper ^5.1 tijsverkoyen/css-to-inline-styles ^2.2.2 vlucas/phpdotenv ^5.2 voku/portable-ascii ^1.4.8

requires (dev) aws/aws-sdk-php ^3.0 doctrine/dbal ^2.6 filp/whoops ^2.4 guzzlehttp/guzzle ^6.5.5|^7.0.1 league/flysystem-cached-adapter ^1.0 mockery/mockery ^1.3.1 orchestra/testbench-core ^6.0 pda/pheanstalk ^4.0 phpunit/phpunit ^8.4|^9.0 predis/predis ^1.1.1 symfony/cache ^5.1

My Scribe config (minus the comments): <?php

return [ 'type' => 'static',

'static' => [
    'output_path' => 'public/docs',
],

'laravel' => [
    'add_routes' => true,

    'docs_url' => '/docs',

    'middleware' => [],
],

'auth' => [
    'enabled' => false,

    'in' => 'bearer',

    'name' => 'token',

    'use_value' => env('SCRIBE_AUTH_KEY'),

    'placeholder' => '{YOUR_AUTH_KEY}',

    'extra_info' => 'You can retrieve your token by visiting your dashboard and clicking <b>Generate API token</b>.',
],

'intro_text' => <<<INTRO
'example_languages' => [
    'bash',
    'javascript',
],

'base_url' => null,

'title' => null,

'description' => '',

'postman' => [
    'enabled' => true,

    'overrides' => [
        // 'info.version' => '2.0.0',
    ],
],

'openapi' => [
    'enabled' => true,

    'overrides' => [
        // 'info.version' => '2.0.0',
    ],
],

'default_group' => 'Endpoints',

'logo' => false,

'router' => 'laravel',

'routes' => [
    [
        'match' => [
            'domains' => ['*'],

            'prefixes' => ['*'],

            'versions' => ['v1'],
        ],
        'include' => [
            // 'users.index', 'healthcheck*'
        ],
        'exclude' => [
            // '/health', 'admin.*'
        ],
        'apply' => [
            'headers' => [
                'Content-Type' => 'application/json',
                'Accept' => 'application/json',
            ],

            'response_calls' => [

                'methods' => ['GET'],

                'config' => [
                    'app.env' => 'documentation',
                    // 'app.debug' => false,
                ],

                'cookies' => [
                    // 'name' => 'value'
                ],

                'queryParams' => [
                    // 'key' => 'value',
                ],

                'bodyParams' => [
                    // 'key' => 'value',
                ],

                'fileParams' => [
                    // 'key' => '/home/me/image.png',
                ],
            ],
        ],
    ],
],

'fractal' => [

    'serializer' => null,
],

'faker_seed' => null,

'strategies' => [
    'metadata' => [
        \Knuckles\Scribe\Extracting\Strategies\Metadata\GetFromDocBlocks::class,
    ],
    'urlParameters' => [
        \Knuckles\Scribe\Extracting\Strategies\UrlParameters\GetFromUrlParamTag::class,
    ],
    'queryParameters' => [
        \Knuckles\Scribe\Extracting\Strategies\QueryParameters\GetFromQueryParamTag::class,
    ],
    'headers' => [
        \Knuckles\Scribe\Extracting\Strategies\Headers\GetFromRouteRules::class,
        \Knuckles\Scribe\Extracting\Strategies\Headers\GetFromHeaderTag::class,
    ],
    'bodyParameters' => [
        \Knuckles\Scribe\Extracting\Strategies\BodyParameters\GetFromFormRequest::class,
        \Knuckles\Scribe\Extracting\Strategies\BodyParameters\GetFromBodyParamTag::class,
    ],
    'responses' => [
        \Knuckles\Scribe\Extracting\Strategies\Responses\UseTransformerTags::class,
        \Knuckles\Scribe\Extracting\Strategies\Responses\UseResponseTag::class,
        \Knuckles\Scribe\Extracting\Strategies\Responses\UseResponseFileTag::class,
        \Knuckles\Scribe\Extracting\Strategies\Responses\UseApiResourceTags::class,
        \Knuckles\Scribe\Extracting\Strategies\Responses\ResponseCalls::class,
    ],
    'responseFields' => [
        \Knuckles\Scribe\Extracting\Strategies\ResponseFields\GetFromResponseFieldTag::class,
    ],
],

'routeMatcher' => \Knuckles\Scribe\Matching\RouteMatcher::class,

'continue_without_database_transactions' => [],

];

Additional info:

shalvah commented 4 years ago

Why are you processing your debug bar routes? You should only be including routes belonging to your API. Update your config so those are excluded.

AliAlican commented 4 years ago

Why are you processing your debug bar routes? You should only be including routes belonging to your API. Update your config so those are excluded.

I changed the configuration so just the api/v4 matching routes apply

image

I still get the same error after a few routes are processed.

shalvah commented 4 years ago

Hmm, looks like it's a problem with closure routes in Laravel (8?). (Should be a straightforward fix for this particular issue, but there may be issues in other places. 🤔) You're using Closure routes, right?

AliAlican commented 4 years ago

I had only two for testing purposes :). Lesson learned, always keep your routes clean :D. Thank you for the help. Also I'm getting this error now

image

should i open a new issue for this?

shalvah commented 4 years ago

Lesson learned, always keep your routes clean

I don't think using Closure routes is not "clean"; it's valid Laravel, after all.

should i open a new issue for this?

yes, please

shalvah commented 4 years ago

I'm not sure what's causing your original closure error. Package works well with closure routes for me. Did you do something strange in your route declaration? Did you install opis/closure or anything like that?

shalvah commented 4 years ago

I think the second issue should be fixed now (2.0.0-beta.1).

aeadedoyin commented 3 years ago

This problem still persists. And it seems to be caused by opis/closure (required by Laravel 8.22.1)

MansoorUmer commented 3 years ago

I'm facing the same problem is there any solution ?

shalvah commented 3 years ago

You'll need to do a bit more investigating, as I can't replicate the issue. Can you also check to be sure you're not documenting web routes?

michalmagic42 commented 3 years ago

The same for me :( Nothing extravagant in the configuration.

Screenshot 2021-04-16 at 14 15 57
shalvah commented 3 years ago

Sorry, guys. You're gonna have to give me something more if you need my help.

michalmagic42 commented 3 years ago

Sorry, guys. You're gonna have to give me something more if you need my help.

The reason is the / route which obviously doesn't include closures, the problem disappeared when the matches have been set up correctly.

The exception is thrown correctly, however, it would be worth catching it to present the one in friendly format :)

sylvacoin commented 3 years ago

I am having similar issues. image

aeadedoyin commented 3 years ago

For those having the same issue, I'd suggest you replace the closure with a Controller(@closureFunction). Pending when this is fixed.

cc @MansoorUmer @sylvacoin @michalmagic42

shalvah commented 3 years ago

Hmm. I'll take another look at this. I think I have an idea of the cause. But I might not be able to get to it for a week or two.

shalvah commented 3 years ago

Currently, my focus is on v3, so it will probably get fixed in v3, and then it may or may not be backported to v2.

sylvacoin commented 3 years ago

So I did a composer update followed by composer dump-autoload. And tried again and it worked out fine.

Mazin-Ibrahim commented 3 years ago

I solved this problem by php artisan route:clear

shalvah commented 3 years ago

I solved this problem by php artisan route:clear

I think this may actually be the solution. As far as I can tell, this isn't a problem in Scribe.