By default CodeIgniter comes with a MVC based approach of serving data. However it is not hard to turn a starter project into a RESTful one.
Prerequisites
- Installed PHP v8.0 or later
- Installed Composer
By the time I'm writing this CodeIgniter 4.5.5 is the most recent version, so I follow the tutorial with that version.
Create the project
After you have the prerequisities you simply run the following command in the terminal:
composer create-project codeigniter4/appstarter <project-name>
This will create a directory with <project-name>
, unless you already have one. In that case an error will appear signaling that <project-name>
is already used.
When the installation is successfully done, you should navigate inside the project and start it with the following:
php spark serve
Now when you open your browser and enter localhost:8080
, you are going to see a html web page. The server works as it should. Now make it serve JSON content.
The example project is available on GitHub.
Update configuration
Locate app/Config/View.php
and change the $saveData
property to false
. We don't want to use views, so we make sure they don't take up memory in vain.
Furthermore, in app/Config/Validation.php
from the $templates
property remove the provided class names, hence we won't render our errors as html.
Delete unnecessarry views
Under app/Views
delete the auto-generated views and adjust or delete app/Controllers/Home.php
to avoid errors. If you deleted it, make sure that app/Config/Routes.php
not maps any endpoint to that controller.
Serve data as JSON
To demonstrate it let's create a new controller:
php spark make:controller TodoController
Add the following method to the controller:
public function getTodo() : ResponseInterface {
$todo = [
'title' => 'Laundry',
'description' => 'Clean the dirty clothes',
'priority' => 4
];
return $this->response
->setStatusCode(200)
->setJson($todo);
}
And register the endpoint in app/Config/Routes.php
:
$routes->get('/todo', [TodoController::class, 'getTodo']);
Now when you test the localhost:8080/todo
URL the result will be a JSON string.
Restful exception handling
Until now everything worked as we expected, but just try to call a not existing endpoint, e.g. localhost:8080/not-yet-defined
. You will see CodeIgniter's built-in error-404 page. That is not desired.
To fix this, open app/Config/Exceptions.php
and locate handler
function. Here we need to provide a custom exception handler that rather returns JSON instead of a webpage.
In app/Libraries
create RestExceptionHandler.php
:
<?php
namespace App\Libraries;
use CodeIgniter\Debug\BaseExceptionHandler;
use CodeIgniter\Debug\ExceptionHandlerInterface;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Throwable;
class RestExceptionHandler extends BaseExceptionHandler implements ExceptionHandlerInterface
{
public function handle(
Throwable $exception,
RequestInterface $request,
ResponseInterface $response,
int $statusCode,
int $exitCode
): void
{
$data = [
'status' => $statusCode,
'message' => $exception->getMessage(),
];
$response->setJson($data)
->setStatusCode($statusCode)
->send();
}
}
And the in the configuration file:
public function handler(int $statusCode, Throwable $exception): ExceptionHandlerInterface
{
return new RestExceptionHandler($this);
}
Now when you enter an invalid URL you will get the following result:
{"status":404,"message":"Page Not Found"}
Later you can customize the handler
function and with branching you can provide multiple exception handler for each exception, but here you can see the idea.