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 😉
Good article, this frameworks is better tran laravel. Nice!
Good Article, how to change the response string from the findAll method
for example filename, become filename and upload path, thank you
you can prepend filename with upload path in the database record itself, the process of adding upload path can be when on previous upload itself.
Hi Abdul. You have used both getRawInput() and getPost() in your examples above. Could you tell me the difference, and where to use each?
you can read the documentation https://codeigniter.com/user_guide/incoming/incomingrequest.html?highlight=getrawinput
How to authenticate this api?
you can create token based auth yourself
halo mas, untuk fitur paginate secara restful seperti laravel adakah di ci4?
kalau bawaan belum ada, buat sendiri saja mas, tinggal model->paginate() dan buat custom response yang dimau.