Menguasai routing CodeIgniter 4: route pattern dan placeholders, grouping, dan auto routing, lalu memahami controller dengan BaseController, method routing, serta cara mereturn view dan JSON response yang benar.

Setelah di episode 3 kita berhasil menginstall CodeIgniter 4 dan membuat hello world dengan auto routing, pada episode ini kita naik satu tingkat: memahami routing secara eksplisit dan controllers — dua komponen yang menentukan URL aplikasi dan bagaimana setiap URL diproses.
Mengapa ini penting? Karena URL adalah kontrak antara aplikasi dan pengguna (atau client API). URL yang konsisten, bisa ditebak, dan aman dari parameter aneh adalah fondasi aplikasi yang profesional. Di episode 4 ini kalian akan belajar mengontrol URL sepenuhnya — bukan lagi "tinggal jalan" dari auto routing.
Semua route terpusat di app/Config/Routes.php. Ada dua mode routing di CodeIgniter 4: defined routing (route eksplisit) dan auto routing (default). Best practice adalah menonaktifkan auto routing dan mendefinisikan semua route eksplisit — lebih jelas, lebih aman.
<?php
use CodeIgniter\Router\RouteCollection;
/**
* @var RouteCollection $routes
*/
$routes->get('/', 'Home::index');
$routes->get('about', 'Pages::about');
$routes->get('posts/(:num)', 'Posts::show/$1');
$routes->get('posts/(:any)', 'Posts::show/$1');Format umum: $routes->get('uri', 'Controller::method'). Segmen pertama pola URL di-kirim sebagai parameter ke method. (:num) berarti angka saja, (:any) berarti segmen apa pun.
CodeIgniter menyediakan placeholder bawaan dan named placeholders yang lebih ekspresif:
// Named placeholder: segmen dicapture dan dikirim ke $1/$2/$3...
$routes->get('blog/(:segment)', 'Blog::show/$1');
$routes->get('blog/(:segment)/(:num)', 'Blog::show/$1/$2');
// Auto routing: segmen di-capture sesuai nama
$routes->get('product/(:num)', 'Product::detail/$1');Placeholder yang tersedia: (:any) — apa pun termasuk slash, (:segment) — satu segmen tanpa slash, (:num) — angka, (:alpha) — alfabet, (:alphanum) — alfanumerik, (:hash) — string dengan tanda. Gunakan placeholder yang paling sempit agar URL menolak input aneh sejak level routing.
Note
Named placeholder dengan {nama} juga didukung (contoh posts/{slug}), namun parameter tetap diakses posisional ($1, $2) di controller. Jangan sampai tertukar dengan sintaks modern di framework lain.
Untuk aplikasi dengan modul, gunakan route groups agar prefix URL konsisten:
$routes->group('admin', static function ($routes) {
$routes->get('dashboard', 'Admin\Dashboard::index');
$routes->get('users', 'Admin\Users::index');
$routes->get('users/(:num)', 'Admin\Users::show/$1');
});Semua route di atas otomatis ber-prefix /admin. Namespace Admin\ menunjukkan controller berada di app/Controllers/Admin/. Group juga bisa memakai filter — kita akan memanfaatkannya untuk proteksi role di episode 12.
Setiap route menunjuk ke controller. BaseController di app/Controllers/BaseController.php adalah class induk untuk semua controller aplikasi — tempat kalian meletakkan properti bersama.
<?php
namespace App\Controllers;
use CodeIgniter\Controller;
abstract class BaseController extends Controller
{
protected $helpers = ['url', 'form'];
protected function render(string $view, array $data = []): string
{
return view($view, $data);
}
}Property $helpers memuat helper secara otomatis di setiap controller turunan — helper url (untuk site_url(), base_url()) dan form (untuk form_open()) hampir selalu dibutuhkan.
URL segmen kedua menentukan method: GET /posts/12 dengan route di atas memanggil Posts::show(12).
<?php
namespace App\Controllers;
class Posts extends BaseController
{
public function index(): string
{
return $this->render('posts/index', ['title' => 'Daftar Post']);
}
public function show(int $id): string
{
$data = [
'title' => "Detail Post #{$id}",
'id' => $id,
];
return $this->render('posts/show', $data);
}
}Perhatikan bahwa parameter method di-ketik int — ini type hinting PHP modern yang dibahas di episode 2. Jika route mengirim angka, controller menerima angka.
Controller bisa mengembalikan HTML view atau data terstruktur (JSON) untuk API:
public function data(): \CodeIgniter\HTTP\ResponseInterface
{
$users = [
['id' => 1, 'name' => 'Arman'],
['id' => 2, 'name' => 'Dewi'],
];
return $this->response->setJSON($users);
}$this->response->setJSON() secara otomatis menetapkan header Content-Type: application/json dan men-encode data. Ini akan menjadi dasar pengembangan REST API di episode 13.
Warning
Jangan mencampur return view dan JSON dalam satu method — kalian harus memilih tipe response berdasarkan konteks. API endpoint mengembalikan JSON, halaman browser mengembalikan HTML. Mencampurnya membuat debug dan integrasi client jadi sulit.
Perintah berikut menampilkan seluruh route yang terdaftar — sangat berguna saat debugging 404:
php spark routesOutput menampilkan method HTTP, URL pattern, controller, dan nama route (jika diberi as). Jika sebuah URL menghasilkan 404 padahal route sudah dibuat, langkah pertama adalah cek file ini.
$routes->get()/post()/... di Config/Routes.php.(:num), (:segment), (:any), (:alpha), (:alphanum).BaseController, method menangani satu request.view() (HTML) atau $this->response->setJSON() (API).Inti yang harus dibawa pulang:
$this->response->setJSON() adalah jembatan ke development API.Di episode 5 selanjutnya kita akan membahas views dan templating — layout dan partial yang reusable, passing data dari controller, section dan extend, serta view cells. Pastikan ci4-app kalian berjalan, karena kita akan membuat layout yang dipakai semua halaman!