Create RESTful API in CodeIgniter 4
In CodeIgniter 4, there is already CodeIgniter\RESTful\ResourceController that make building RESTful API easier. It can consume the model by provide modelName property.
Preparation
1. Register Routes
// app/Config/Routes.php
$routes->resource('products');
2. Create Model and Entity Classes
For example, we have the ProductModel class:
<?php namespace App\Models;
use App\Entities\Product;
use CodeIgniter\Model;
class ProductModel extends Model
{
protected $table = 'product';
/**
* $returnType as entity class in RESTful API might not work in CodeIgniter 4.0.2.
* You can define as "object" at CodeIgniter 4.0.2 for RESTful API usage.
*
* protected $returnType = 'object';
*
*/
protected $returnType = Product::class;
protected $allowedFields = [
'product_code',
'product_name',
];
protected $validationRules = [
'product_code' => 'required|alpha_numeric|exact_length[5]|is_unique[product.product_code,id,{id}]',
'product_name' => 'required|alpha_numeric_space|min_length[3]|max_length[255]|is_unique[product.product_name,id,{id}]',
];
}
Above model require entity class, so, we can create as follow:
<?php namespace App\Entities;
use CodeIgniter\Entity;
class Product extends Entity
{
protected $attributes = [
'product_code' => null,
'product_name' => null,
];
// filter on create/update data if necessary
public function setProductCode(string $productCode): self
{
$this->attributes['product_code'] = strtoupper($productCode);
return $this;
}
// filter on create/update data if necessary
public function setProductName(string $productName): self
{
$this->attributes['product_name'] = ucwords($productName);
return $this;
}
}
3. Ensure the pages has “csrf” filter DISABLED for the RESTful API pages
CSRF usually uses only for public web interation forms. For API, we can use authorization token (eg: for Oauth usage). We can disable csrf filter in app/Config/Filters.php like the following:
<?php namespace Config;
use App\Filters\PostRequestOnly;
use CodeIgniter\Config\BaseConfig;
class Filters extends BaseConfig
{
// ...
public $globals = [
'before' => [
'csrf' => [
'except' => [
'/products',
'/products/*',
],
],
],
];
// ...
}
The API
We can create a controller for it, that extends CodeIgniter\RESTful\ResourceController:
<?php namespace App\Controllers;
use CodeIgniter\RESTful\ResourceController;
class Products extends ResourceController
{
protected $modelName = 'App\Models\ProductModel';
protected $format = 'json';
}
For display all products, we can create method index:
// ...
public function index()
{
return $this->respond($this->model->findAll());
}
// ...
This is the output of all products:

For display product by id, we can add method show:
// ...
public function show($id = null)
{
$record = $this->model->find($id);
if (! $record)
{
return $this->failNotFound(sprintf(
'product with id %d not found',
$id
));
}
return $this->respond($record);
}
// ...
This is the output when product found and not found:

For create new product data, we can add method create:
// ...
public function create()
{
$data = $this->request->getPost();
if (! $this->model->save($data))
{
return $this->fail($this->model->errors());
}
return $this->respondCreated($data, 'product created');
}
// ...
Above, we use getPost() from request object to get POST data. This is the output when product creation is succeed and failed:

For update product data, we can add method update:
// ...
public function update($id = null)
{
$data = $this->request->getRawInput();
$data['id'] = $id;
if (! $this->model->save($data))
{
return $this->fail($this->model->errors());
}
return $this->respond($data, 200, 'product updated');
}
// ...
Above, we use getRawInput() from request object to get PUT data. Currently, there is no “respondUpdated” method, I created Pull Request for it at https://github.com/codeigniter4/CodeIgniter4/pull/2816 for addition of “respondUpdated” method.
This is the output when product update is succeed and failed:

Now, the last one, the delete, we can add delete method:
// ...
public function delete($id = null)
{
$delete = $this->model->delete($id);
if ($this->model->db->affectedRows() === 0)
{
return $this->failNotFound(sprintf(
'product with id %d not found or already deleted',
$id
));
}
return $this->respondDeleted(['id' => $id], 'product deleted');
}
//...
This is the output when product delete is succeed and failed:

That’s it 😉
9 comments