I am unable to create a Restful API using the CodeIgniter 4 framework.
I am using $routes->resource()
to define the methods. However, I am unable to get http://localhost:8080/type-blood
and other addresses to return what I want.
I correctly configured the database in the project and made a selection to see the data.
What return to me in Postman is this:
{
"title": "CodeIgniter\Exceptions\PageNotFoundException",
"type": "CodeIgniter\Exceptions\PageNotFoundException",
"code": 404,
"message": "Controller or its method is not found: \App\Controllers\App\Controllers\TypeBloodController::index",
"file": "/home/faker/CodeIgniter/c4/vendor/codeigniter4/framework/system/CodeIgniter.php",
"line": 988,
"trace": [
{
"file": "/home/faker/CodeIgniter/c4/vendor/codeigniter4/framework/system/CodeIgniter.php",
"line": 988,
"function": "forPageNotFound",
"class": "CodeIgniter\Exceptions\PageNotFoundException",
"type": "::"
},
{
"file": "/home/faker/CodeIgniter/c4/vendor/codeigniter4/framework/system/CodeIgniter.php",
"line": 370,
"function": "display404errors",
"class": "CodeIgniter\CodeIgniter",
"type": "->"
},
{
"file": "/home/faker/CodeIgniter/c4/public/index.php",
"line": 79,
"function": "run",
"class": "CodeIgniter\CodeIgniter",
"type": "->"
},
{
"file": "/home/faker/CodeIgniter/c4/vendor/codeigniter4/framework/system/Commands/Server/rewrite.php",
"line": 47,
"args": [
"/home/faker/CodeIgniter/c4/public/index.php"
],
"function": "require_once"
}
]
}
Route.php
<?php
use CodeIgniterRouterRouteCollection;
use AppControllersTypeBloodController;
/**
* @var RouteCollection $routes
*/
$routes->resource('type-blood', ['controller' => TypeBloodController::class]);
$routes->get('/', 'Home::index');
TypeBloodController.php
<?php
namespace AppControllers;
use AppControllersBaseController;
use AppModelsTypeBloodModel;
class TypeBloodController extends BaseController
{
public function index()
{
$type_blood = new TypeBloodModel();
$datas = $type_blood->findAll();
$this->response->setContentType('application/json');
return $this->response->setJSON($datas);
}
public function store()
{
$type_blood = new TypeBloodModel();
$validation = $type_blood->getRuleGroup('blood_store');
$this->response->setContentType('application/json');
return $this->response->setStatusCode(200)->setJSON(['message' => 'Insertion done.']);
}
public function show($id)
{
$type_blood = new TypeBloodModel();
$register = $type_blood->find($id);
if (!$type_blood) {
return $this->response->setStatusCode(404)->setJSON(['message' => "Register not found."]);
}
$this->response->setContentType('application/json');
return $this->response->setJSON($register);
}
public function update($id)
{
$type_blood = new TypeBloodModel();
$register = $type_blood->find($id);
if (!$register) {
return $this->response->setStatusCode(404)->setJSON(['message' => "Register updated."]);
}
$validation = $registro->getRuleGroup('blood_update');
$this->response->setContentType('application/json');
return $this->response->setJSON($register);
}
public function destroy($id)
{
$type_blood = new TypeBloodModel();
$register = $type_blood->find($id);
if (!$register) {
return $this->response->setStatusCode(404)->setJSON(['message' => "Register not found"]);
}
$register->delete($id);
$this->response->setContentType('application/json');
return $this->response->setStatusCode(200)->setJSON(['message' => 'Exclusion done.']);
}
}
2
Answers
Unfortunately you cannot use a qualified names for specifying the controller option.
According the documentation it is possible, but it seems to be a minor bug, because in this case it duplicates the namespaces.
You can always check your routes with the spark command. Check the handler column.
In my case the handler is: AppControllersAppControllersHome::index, but it should be: AppControllersHome::index
You can fix it simply:
Note: if your resource and controller names are the same, you can omit the controller option. So you can technically change the name of the controller to TypeBlood and file name to TypeBlood.php. Then simply delete the controller option.
Note: if your controller is not in the AppControllers namespace, you can specify with the namespace option. For example:
I created a bug issue report, so maybe it will be fixed in the later version.
Explanation
If the controller is provided without a leading backslash (), the default namespace will be prepended.
Default Namespace
Excerpt from
CodeIgniter4/app/Config/Routing.php
Solution
app/Config/Routes.php
$routes->setDefaultNamespace('');
$routes->get('/', 'Home::index');
$routes->get('/', [Home::class, 'index']);
Example