Belajar CodeIgniter - REST API Development
Episode 13 of 27

Belajar CodeIgniter - REST API Development

Membangun REST API dengan ResourceController, routing resource yang otomatis, format JSON response yang konsisten, API versioning, serta workflow testing API dengan Postman.

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Sejauh ini aplikasi kita melayani halaman HTML untuk browser. Di episode 13 ini kita membuka pintu lain: REST API — antarmuka yang mengembalikan data terstruktur (JSON) sehingga bisa dikonsumsi aplikasi mobile, SPA, atau integrasi antar sistem.

Mengapa penting? Karena hampir semua produk modern memisahkan frontend dan backend, atau setidaknya menyediakan API publik. CodeIgniter 4 menyederhanakan ini dengan ResourceController dan resource routing — kalian mendapat endpoint CRUD standar hanya dengan beberapa baris.

Resource Routing

Satu baris di app/Config/Routes.php menghasilkan 6 endpoint standar:

Resource routing
$routes->resource('posts');
MethodURLFungsiDefault controller method
GET/postsDaftar semuaindex()
GET/posts/(:num)Detail satushow($id)
POST/postsBuat barucreate()
PUT/PATCH/posts/(:num)Updateupdate($id)
DELETE/posts/(:num)Hapusdelete($id)
GET/posts/newForm buat (opsional)new()
GET/posts/(:num)/editForm edit (opsional)edit($id)

Jika kalian tidak butuh endpoint form (new/edit), nonaktifkan dengan 'only' => ['index','show','create','update','delete'].

ResourceController

Buat controller RESTful:

Buat ResourceController
php spark make:controller Api/Posts --restful
app/Controllers/Api/Posts.php
<?php
 
namespace App\Controllers\Api;
 
use App\Controllers\BaseController;
use App\Models\PostModel;
use CodeIgniter\RESTful\ResourceController;
 
class Posts extends ResourceController
{
    protected $modelName = 'App\Models\PostModel';
    protected $format    = 'json';
 
    public function index(): \CodeIgniter\HTTP\ResponseInterface
    {
        $posts = $this->model->where('status', 'published')
                             ->orderBy('created_at', 'DESC')
                             ->findAll();
 
        return $this->respond($posts);
    }
 
    public function show($id = null): \CodeIgniter\HTTP\ResponseInterface
    {
        $post = $this->model->find($id);
 
        if ($post === null) {
            return $this->failNotFound('Post tidak ditemukan');
        }
 
        return $this->respond($post);
    }
 
    public function create(): \CodeIgniter\HTTP\ResponseInterface
    {
        $rules = [
            'title' => 'required|max_length[255]',
            'slug'  => 'required|alpha_dash|is_unique[posts.slug]',
        ];
 
        if (! $this->validate($rules)) {
            return $this->failValidationErrors($this->validator->getErrors());
        }
 
        $id = $this->model->insert([
            'title' => $this->request->getPost('title'),
            'slug'  => $this->request->getPost('slug'),
        ]);
 
        return $this->respondCreated(['id' => $id]);
    }
 
    public function update($id = null): \CodeIgniter\HTTP\ResponseInterface
    {
        if ($this->model->find($id) === null) {
            return $this->failNotFound('Post tidak ditemukan');
        }
 
        $this->model->update($id, [
            'title' => $this->request->getPost('title') ?? $this->request->getRawInput()['title'] ?? '',
        ]);
 
        return $this->respondUpdated(['id' => $id]);
    }
 
    public function delete($id = null): \CodeIgniter\HTTP\ResponseInterface
    {
        if ($this->model->find($id) === null) {
            return $this->failNotFound('Post tidak ditemukan');
        }
 
        $this->model->delete($id);
 
        return $this->respondDeleted(['id' => $id]);
    }
}

Property $format = 'json' membuat semua response otomatis di-encode JSON. Helper response bawaan ResourceController memberi format konsisten:

HelperStatus codeArti
respond($data)200Sukses
respondCreated($data)201Data berhasil dibuat
respondUpdated($data)200Data diperbarui
respondDeleted($data)200Data dihapus
failNotFound($msg)404Tidak ditemukan
failValidationErrors($errors)422Validasi gagal

Tip

Untuk method PUT, CodeIgniter membaca body JSON mentah lewat $this->request->getRawInput()['field'] — bukan getPost() yang hanya membaca form-urlencoded. Pastikan kalian memakai cara yang benar sesuai format request client.

Struktur Response yang Konsisten

Consistency adalah aturan pertama API. Response kita selalu berbentuk:

Response JSON sukses
{
  "id": 12,
  "title": "Belajar REST API",
  "slug": "belajar-rest-api",
  "status": "published",
  "created_at": "2026-08-16 09:00:00"
}
Response JSON error
{
  "error": "Post tidak ditemukan"
}

Dokumentasikan struktur ini untuk client. Di produksi, pertimbangkan format envelope (data, meta, errors) agar client bisa mengecek status secara terprogram — standar yang kita pilih di sini cukup untuk series ini.

API Versioning

API akan berevolusi, dan perubahan yang memecah client tidak boleh terjadi diam-diam. Solusi klasiknya: versioning di URL (/api/v1/posts).

Route API dengan versioning
$routes->group('api/v1', ['namespace' => 'App\Controllers\Api\V1'], static function ($routes) {
    $routes->resource('posts');
    $routes->resource('categories');
});

Namespace App\Controllers\Api\V1 menunjuk ke folder app/Controllers/Api/V1/. Saat API berubah, kalian buat app/Controllers/Api/V2/ dan route baru api/v2 — client lama tetap jalan di v1 sementara client baru bermigrasi ke v2.

Warning

Jangan menghapus versi lama secara mendadak. Umumkan deprecation, beri masa transisi, lalu hapus setelah client benar-benar pindah. Versioning di URL memang tidak se-elok header Accept, tapi jauh lebih mudah dipahami dan di-debug.

Testing API dengan Postman

Postman mempermudah pengujian endpoint. Alur dasar:

Jalankan server dan uji endpoint
php spark serve --port 8080
curl -i http://localhost:8080/api/v1/posts
Response dari curl
HTTP/1.1 200 OK
Content-Type: application/json
 
[{"id":1,"title":"Hello World","slug":"hello-world","status":"published","created_at":"2026-08-16 09:00:00"}]

Di Postman:

  1. Buat request GET http://localhost:8080/api/v1/posts.
  2. Untuk POST, pilih body raw → JSON, kirim {"title":"Post Baru","slug":"post-baru"}.
  3. Cek status code: 201 untuk create, 422 untuk validasi gagal, 404 untuk not found.

Note

Di episode 8 filter CSRF kita aktifkan global. Untuk API endpoint, CSRF dikecualikan (ganti dengan API key/JWT — episode 19). Jika kalian mendapat error CSRF di /api/*, tambahkan except pada filter csrf untuk prefix api/.

Ringkasan REST API Development

  • $routes->resource('posts') menghasilkan 7 endpoint standar CRUD.
  • ResourceController + $format = 'json' + helper respond/fail = response konsisten.
  • Baca body JSON lewat getRawInput(), bukan getPost().
  • Versioning via api/v1/api/v2 + namespace per versi.
  • Uji endpoint dengan curl/Postman; cek status code dengan benar.

Penutup

Inti yang harus dibawa pulang:

  • Resource routing menghemat banyak boilerplate untuk CRUD API.
  • Gunakan helper respond*/fail* agar format error konsisten.
  • getRawInput() untuk body JSON; versioning URL untuk evolusi API.
  • Exclude CSRF untuk route API; ganti dengan token auth (episode 19).

Di episode 14 selanjutnya kita akan membahas caching & performance — cache drivers File/Redis/Memcached, page cache dan query caching, serta praktik cache list API dengan invalidation yang benar. Aplikasi kalian mulai berurusan dengan traffic!

Belajar CodeIgniter - REST API Development | Belajar CodeIgniter