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
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