Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When declaring multiple resource routes, all but the first fail to pass the parameter correctly. #1792

Open
drahija-gli opened this issue Dec 30, 2021 · 0 comments

Comments

@drahija-gli
Copy link

Q A
Bug? unsure
New Feature? no
Framework Lumen
Framework version 8.3.1
Package version 3.0.7
PHP version 7.4

Actual Behaviour

When setting up multiple api resource routes, only the first resource is working as expected, the others return an error similar to Unable to resolve dependency [Parameter #0 [ <required> $user_id ]] in class App\\Http\\Controllers\\UserController

Here's my web.php file:

<?php

/** @var \Laravel\Lumen\Routing\Router $router */

use App\Http\Controllers\ApiAuthController;
use App\Http\Controllers\IndexController;
use App\Http\Controllers\CompanyController;
use App\Http\Controllers\RoleController;
use App\Http\Controllers\UserAuthController;
use App\Http\Controllers\UserController;

$api = app('Dingo\Api\Routing\Router');

$api->version('v1', function ($api) {

    $api->group(['middleware' => ['log']], function ($api) {
        $api->post('/login', [ApiAuthController::class, 'postAuthenticate']);
        $api->post('/users/login', [UserAuthController::class, 'postAuthenticate']);
    });

    $api->group(['middleware' => ['auth', 'log']], function ($api) {

        //Root Route. This prevents any leaky details if someone tries to hit the API in the browser
        $api->get('/', [IndexController::class, 'getIndex']);

        //Company Routes
        $api->resource('companies', CompanyController::class, [
            'parameters' => ['companies' => 'company_id'],
        ]);

        //Role Routes
        $api->resource('roles', RoleController::class, [
            'parameters' => ['roles' => 'role_id'],
        ]);

        //User Auth Routes
        $api->post('/users/logout', [UserAuthController::class, 'postLogout']);
        $api->post('/users/refresh', [UserAuthController::class, 'postRefresh']);

        //User Routes
        $api->resource('users', UserController::class, [
            'parameters' => ['users' => 'user_id'],
        ]);
    });
});

If I send a GET request to /companies/5837991a-9f8d-47d7-9453-13e1b67bae35 I get a 200 OK response and the request data. However if I send a GET request to /roles/0553a087-457a-4124-8669-ca29f4c06c64 or users/46e8b3a5-085d-4f4a-bf30-411159591b56 I get the 500 Internal Server Error posted above (substitute Controller/Key details). If however, I move the API Resource statements around, for example, putting the Role Routes before the Company Routes, the request to /roles/0553a087-457a-4124-8669-ca29f4c06c64 will work, but the request to /companies/5837991a-9f8d-47d7-9453-13e1b67bae35 will fail.

The show method from CompanyController.php

    public function show($company_id)
    {
        $company = Company::findOrFail($company_id);
        return $this->response->item($company, new CompanyTransformer);
    }

The show method from RoleController.php

    public function show($role_id)
    {
        $role = Role::findOrFail($role_id);
        return $this->response->item($role, new RoleTransformer);
    }

Stack Trace of Error:

{
    "message": "Unable to resolve dependency [Parameter #0 [ <required> $user_id ]] in class App\\Http\\Controllers\\UserController",
    "status_code": 500,
    "debug": {
        "line": 182,
        "file": "/mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/illuminate/container/BoundMethod.php",
        "class": "Illuminate\\Contracts\\Container\\BindingResolutionException",
        "trace": [
            "#0 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/illuminate/container/BoundMethod.php(124): Illuminate\\Container\\BoundMethod::addDependencyForCallParameter()",
            "#1 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/illuminate/container/BoundMethod.php(36): Illuminate\\Container\\BoundMethod::getMethodDependencies()",
            "#2 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/illuminate/container/Util.php(40): Illuminate\\Container\\BoundMethod::Illuminate\\Container\\{closure}()",
            "#3 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/illuminate/container/BoundMethod.php(93): Illuminate\\Container\\Util::unwrapIfClosure()",
            "#4 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/illuminate/container/BoundMethod.php(37): Illuminate\\Container\\BoundMethod::callBoundMethod()",
            "#5 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/illuminate/container/Container.php(653): Illuminate\\Container\\BoundMethod::call()",
            "#6 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(389): Illuminate\\Container\\Container->call()",
            "#7 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(355): Laravel\\Lumen\\Application->callControllerCallable()",
            "#8 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(329): Laravel\\Lumen\\Application->callLumenController()",
            "#9 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(282): Laravel\\Lumen\\Application->callControllerAction()",
            "#10 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(262): Laravel\\Lumen\\Application->callActionOnArrayBasedRoute()",
            "#11 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/laravel/lumen-framework/src/Routing/Pipeline.php(48): Laravel\\Lumen\\Application->Laravel\\Lumen\\Concerns\\{closure}()",
            "#12 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/app/Http/Middleware/BeforeRequestLogs.php(56): Laravel\\Lumen\\Routing\\Pipeline->Laravel\\Lumen\\Routing\\{closure}()",
            "#13 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/illuminate/pipeline/Pipeline.php(167): App\\Http\\Middleware\\BeforeRequestLogs->handle()",
            "#14 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/laravel/lumen-framework/src/Routing/Pipeline.php(30): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()",
            "#15 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/app/Http/Middleware/Authenticate.php(42): Laravel\\Lumen\\Routing\\Pipeline->Laravel\\Lumen\\Routing\\{closure}()",
            "#16 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/illuminate/pipeline/Pipeline.php(167): App\\Http\\Middleware\\Authenticate->handle()",
            "#17 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/laravel/lumen-framework/src/Routing/Pipeline.php(30): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()",
            "#18 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/dingo/api/src/Http/Middleware/PrepareController.php(45): Laravel\\Lumen\\Routing\\Pipeline->Laravel\\Lumen\\Routing\\{closure}()",
            "#19 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/illuminate/pipeline/Pipeline.php(167): Dingo\\Api\\Http\\Middleware\\PrepareController->handle()",
            "#20 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/laravel/lumen-framework/src/Routing/Pipeline.php(30): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()",
            "#21 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/illuminate/pipeline/Pipeline.php(103): Laravel\\Lumen\\Routing\\Pipeline->Laravel\\Lumen\\Routing\\{closure}()",
            "#22 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(426): Illuminate\\Pipeline\\Pipeline->then()",
            "#23 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(263): Laravel\\Lumen\\Application->sendThroughPipeline()",
            "#24 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(237): Laravel\\Lumen\\Application->handleFoundRoute()",
            "#25 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(173): Laravel\\Lumen\\Application->handleDispatcherResponse()",
            "#26 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(429): Laravel\\Lumen\\Application->Laravel\\Lumen\\Concerns\\{closure}()",
            "#27 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(175): Laravel\\Lumen\\Application->sendThroughPipeline()",
            "#28 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/dingo/api/src/Routing/Adapter/Lumen.php(116): Laravel\\Lumen\\Application->dispatch()",
            "#29 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/dingo/api/src/Routing/Router.php(518): Dingo\\Api\\Routing\\Adapter\\Lumen->dispatch()",
            "#30 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/dingo/api/src/Http/Middleware/Request.php(126): Dingo\\Api\\Routing\\Router->dispatch()",
            "#31 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/illuminate/pipeline/Pipeline.php(128): Dingo\\Api\\Http\\Middleware\\Request->Dingo\\Api\\Http\\Middleware\\{closure}()",
            "#32 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/illuminate/pipeline/Pipeline.php(103): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()",
            "#33 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/dingo/api/src/Http/Middleware/Request.php(127): Illuminate\\Pipeline\\Pipeline->then()",
            "#34 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/dingo/api/src/Http/Middleware/Request.php(103): Dingo\\Api\\Http\\Middleware\\Request->sendRequestThroughRouter()",
            "#35 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/illuminate/pipeline/Pipeline.php(167): Dingo\\Api\\Http\\Middleware\\Request->handle()",
            "#36 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/laravel/lumen-framework/src/Routing/Pipeline.php(30): Illuminate\\Pipeline\\Pipeline->Illuminate\\Pipeline\\{closure}()",
            "#37 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/illuminate/pipeline/Pipeline.php(103): Laravel\\Lumen\\Routing\\Pipeline->Laravel\\Lumen\\Routing\\{closure}()",
            "#38 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(426): Illuminate\\Pipeline\\Pipeline->then()",
            "#39 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(175): Laravel\\Lumen\\Application->sendThroughPipeline()",
            "#40 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php(112): Laravel\\Lumen\\Application->dispatch()",
            "#41 /mnt/c/www/api.myapi.io.local/data/api-myapi-io/public/index.php(28): Laravel\\Lumen\\Application->run()",
            "#42 {main}"
        ]
    }

While trying to track down the issue, what I'm finding is in the BoundMethod.php file, it's looking for $paramName (user_id) in the $parameters array. However, the parameters array is indexing the value as user. From what I'm finding in the Naming Resource Route Parameters it looks like this is working for the first resource, but subsequent resources are using the default singularized version.

array(1) {
    [
        "user"
    ]=>
  string(36) "46e8b3a5-085d-4f4a-bf30-411159591b56"
}

Expected Behaviour

I would expect that the various resource routes would all assign the parameter variables and load the controller as expected.

Steps to Reproduce

I believe all of the various code snippets and other items needed are all spelled out in the section above.

Possible Solutions

It looks like I could remove the specified parameters and use the singular variable in the controllers, but I like passing the variable like user_id as opposed to $user and reserve the singular for the model.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant