meder omuraliev
meder omuraliev

Reputation: 186762

Cake - Setup routing to support versioned API controllers?

I want to be able to support multiple versioned endpoints from my api simultaneously, such as:

/api/v1.1/counties/get
/api/v1.2/counties/get

But in trying to implement the routing for this, a bit perplexed as to how Cake wants this as I keep getting a

Error: Controller class Counties could not be found.

Attempt 1:

Router::scope('/api', function ($routes) {

    $routes->setExtensions(['json']);
    $routes->fallbacks('DashedRoute');

    $versions = [
        1.1
    ];

    foreach ($versions as $version) {
        $routes->scope('/' . $version, function($routes) {

            $routes->resources('Counties', [
                'controller' => 'Counties',
                'prefix' => 'api',
                'map' => [
                    'get' => [
                        'action' => 'get',
                    ]
                ]
            ]);

        }
    }

});

Attempt 2:

Router::scope('/api', function($routes) {

    $routes->scope('/v1.1', function($routes) {
        $routes->resources('Counties', [
            'controller' => 'Counties',
            'map' => [
                'get' => [
                    'action' => 'get'
                ]   
            ]   
        ]); 
    }); 

    $routes->connect(
        '/v1.1/counties/get',
        [   
            'controller' => 'Counties',
            'action' => 'get',
        ]   
    );  
});

The directory structure I'm currently using (which is still open for debate):

src/Controller/Api/V1.1, which would use base controllers from src/Controller/Api and extend them with stub methods to override if needed. Most of my "fat" is in the models.

and src/Controller/Api/V1.1/CountiesController.php has:

namespace App\Controller\Api\V1.1;

class CountiesController extends AppController
{
}

Would appreciate any insight

Upvotes: 2

Views: 1083

Answers (1)

ndm
ndm

Reputation: 60503

You cannot use chars like dots in the namespace (folder) structure, as that is invalid PHP.

What you are looking for is using prefix routing and the path option, so that you can connect prefixes that are valid in namespaces, and supply a custom path (URL segment) for the route, something like:

Router::prefix('api', function (RouteBuilder $routes) {
    // ...

    $routes->prefix('v11', ['path' => '/v1.1'], function (RouteBuilder $routes) {
        $routes->resources('Counties', [
            'map' => [
                'get' => [
                    'action' => 'get'
                ]  
            ]
        ]);
    });
});

That would connect the following routes (you can check the connected routes in the shell via bin/cake routes):

+---------------------+-----------------------+--------------------------------------------------------------------------------------------------+
| Route name          | URI template          | Defaults                                                                                         |
+---------------------+-----------------------+--------------------------------------------------------------------------------------------------+
| v11:counties:index  | api/v1.1/counties     | {"controller":"Counties","action":"index","_method":"GET","prefix":"v11","plugin":null}          |
| v11:counties:add    | api/v1.1/counties     | {"controller":"Counties","action":"add","_method":"POST","prefix":"v11","plugin":null}           |
| v11:counties:view   | api/v1.1/counties/:id | {"controller":"Counties","action":"view","_method":"GET","prefix":"v11","plugin":null}           |
| v11:counties:edit   | api/v1.1/counties/:id | {"controller":"Counties","action":"edit","_method":["PUT","PATCH"],"prefix":"v11","plugin":null} |
| v11:counties:delete | api/v1.1/counties/:id | {"controller":"Counties","action":"delete","_method":"DELETE","prefix":"v11","plugin":null}      |
| v11:counties:get    | api/v1.1/counties/get | {"controller":"Counties","action":"get","_method":"GET","prefix":"v11","plugin":null}            |
+---------------------+-----------------------+--------------------------------------------------------------------------------------------------+

The CountiesController class would then be expected in

src/Controller/Api/V11/CountiesController.php

with a namespace of:

App\Controller\Api\V11

See also

Upvotes: 5

Related Questions