1. Routing là gì?
Routing (định tuyến) là quá trình ánh xạ một URL request từ người dùng đến một controller và phương thức cụ thể trong ứng dụng. Khi người dùng truy cập một địa chỉ như https://example.com/products/detail/5, hệ thống routing sẽ quyết định đoạn code nào sẽ xử lý request đó.
Mặc định, CodeIgniter 4 sử dụng cơ chế Auto Routing dựa trên URI, nhưng bạn có thể (và nên) định nghĩa các route thủ công để kiểm soát chặt chẽ hơn.
2. Cấu trúc file Routes.php
Tất cả các route trong CodeIgniter 4 được định nghĩa trong file app/Config/Routes.php. Đây là nơi bạn sẽ khai báo mọi quy tắc định tuyến cho ứng dụng.
<?php
namespace Config;
use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Router\RouteCollection;
/**
* @var RouteCollection $routes
*/
$routes->get('/', 'Home::index');
Biến $routes là một instance của RouteCollection, cung cấp nhiều phương thức để bạn định nghĩa route theo phương thức HTTP tương ứng.
3. Các phương thức HTTP cơ bản
CodeIgniter 4 hỗ trợ đầy đủ các phương thức HTTP phổ biến. Mỗi phương thức có một hàm tương ứng trong RouteCollection:
<?php
// Route cho GET
$routes->get('products', 'ProductController::index');
// Route cho POST
$routes->post('products/create', 'ProductController::store');
// Route cho PUT
$routes->put('products/update/(:num)', 'ProductController::update/$1');
// Route cho DELETE
$routes->delete('products/delete/(:num)', 'ProductController::delete/$1');
// Route cho PATCH
$routes->patch('products/patch/(:num)', 'ProductController::patch/$1');
// Route cho OPTIONS
$routes->options('products', 'ProductController::options');
Ngoài ra, bạn có thể dùng $routes->add() để chỉ định phương thức HTTP một cách linh hoạt:
<?php
$routes->add('products', 'ProductController::index', ['get', 'post']);
4. Route với tham số động (Placeholder)
CodeIgniter 4 cung cấp nhiều loại placeholder để bắt tham số động trong URL:
<?php
// (:num) - chỉ khớp với số
$routes->get('products/(:num)', 'ProductController::detail/$1');
// (:alpha) - chỉ khớp với chữ cái
$routes->get('category/(:alpha)', 'CategoryController::show/$1');
// (:alphanum) - khớp với chữ cái và số
$routes->get('slug/(:alphanum)', 'SlugController::show/$1');
// (:segment) - khớp với bất kỳ ký tự nào trừ dấu /
$routes->get('blog/(:segment)', 'BlogController::detail/$1');
// (:any) - khớp với mọi thứ bao gồm dấu /
$routes->get('files/(:any)', 'FileController::serve/$1');
Bạn cũng có thể sử dụng nhiều placeholder trong cùng một route:
<?php
$routes->get('blog/(:num)/(:segment)', 'BlogController::show/$1/$2');
5. Đặt tên cho route (Named Routes)
Đặt tên cho route giúp bạn dễ dàng tạo URL trong view hoặc controller mà không cần hard-code đường dẫn:
<?php
$routes->get('products/detail/(:num)', 'ProductController::detail/$1', ['as' => 'product_detail']);
Sử dụng tên route để sinh URL:
<?php
// Trong controller hoặc view
$url = route_to('product_detail', 5);
// Kết quả: /products/detail/5
// Hoặc dùng helper
$url = url_to('ProductController::detail', 5);
6. Nhóm route (Route Groups)
Route Group cho phép bạn áp dụng chung một tiền tố (prefix) hoặc filter cho nhiều route cùng lúc. Đây là kỹ thuật cực kỳ hữu ích khi xây dựng các module như admin, api, auth...
<?php
$routes->group('admin', function ($routes) {
$routes->get('dashboard', 'Admin\DashboardController::index');
$routes->get('users', 'Admin\UserController::index');
$routes->get('users/edit/(:num)', 'Admin\UserController::edit/$1');
});
Kết quả các URL sẽ là:
/admin/dashboard/admin/users/admin/users/edit/5
Bạn cũng có thể lồng nhiều group với nhau:
<?php
$routes->group('admin', function ($routes) {
$routes->group('api', function ($routes) {
$routes->get('users', 'Admin\Api\UserController::index');
});
});
// URL: /admin/api/users
7. Áp dụng Filter cho Route
Filter là lớp trung gian cho phép bạn kiểm tra request trước khi vào controller. Ví dụ điển hình là xác thực đăng nhập:
<?php
$routes->group('admin', ['filter' => 'auth'], function ($routes) {
$routes->get('dashboard', 'Admin\DashboardController::index');
$routes->get('users', 'Admin\UserController::index');
});
Bạn cũng có thể áp dụng filter cho từng route riêng lẻ:
<?php
$routes->get('profile', 'UserController::profile', ['filter' => 'auth']);
Hoặc nhiều filter cùng lúc:
<?php
$routes->get('admin/settings', 'Admin\SettingController::index', ['filter' => ['auth', 'admin']]);
8. Route mặc định và Route 404
Route mặc định xử lý khi người dùng truy cập vào gốc của ứng dụng:
<?php
$routes->get('/', 'Home::index');
Để tùy chỉnh trang 404, bạn có thể định nghĩa trong app/Config/Routes.php:
<?php
$routes->set404Override('App\Controllers\Errors::show404');
Hoặc dùng closure:
<?php
$routes->set404Override(function () {
return view('errors/custom_404');
});
9. Auto Routing (Improved) và Auto Routing (Legacy)
CodeIgniter 4 cung cấp hai chế độ auto routing, có thể bật/tắt trong app/Config/Routing.php:
<?php
// Bật Auto Routing (Improved) - khuyến nghị
public bool $autoRoute = true;
public bool $autoRouteLegacy = false;
Auto Routing (Improved) yêu cầu phương thức HTTP phải khớp với tên hàm (ví dụ getIndex(), postCreate()), an toàn hơn.
Auto Routing (Legacy) cho phép truy cập mọi public method, kém an toàn hơn và đã bị deprecate.
10. Route với Closure
Với các route đơn giản, bạn có thể dùng closure thay vì tạo controller:
<?php
$routes->get('about', function () {
return view('about');
});
$routes->get('hello/(:segment)', function ($name) {
return "Xin chào, {$name}!";
});
11. Route cho RESTful API
CodeIgniter 4 hỗ trợ tạo nhanh các route RESTful với resource():
<?php
$routes->resource('photos', 'PhotoController');
Lệnh trên sẽ tự động tạo các route sau:
GET /photos→index()GET /photos/new→new()POST /photos→create()GET /photos/(:num)→show()GET /photos/(:num)/edit→edit()PUT/PATCH /photos/(:num)→update()DELETE /photos/(:num)→delete()
Nếu chỉ cần API (không có new/edit), dùng resource('photos', 'PhotoController', ['only' => ['index', 'show', 'create', 'update', 'delete']]).
12. Một số kỹ thuật nâng cao khác
12.1. Route với domain và subdomain
<?php
$routes->group('', ['hostname' => 'api.example.com'], function ($routes) {
$routes->get('users', 'Api\UserController::index');
});
12.2. Route với namespace
<?php
$routes->group('admin', ['namespace' => 'App\Controllers\Admin'], function ($routes) {
$routes->get('dashboard', 'DashboardController::index');
});
12.3. Chuyển hướng route
<?php
$routes->addRedirect('old-url', 'new-url', 301);
$routes->get('old-page', function () {
return redirect()->to('/new-page');
});
12.4. Route ưu tiên và override
CodeIgniter 4 duyệt route theo thứ tự khai báo, route nào khai báo trước sẽ được ưu tiên. Vì vậy, hãy đặt các route cụ thể trước, route tổng quát sau:
<?php
// Đúng: cụ thể trước
$routes->get('products/featured', 'ProductController::featured');
$routes->get('products/(:num)', 'ProductController::detail/$1');
// Sai: route động sẽ "nuốt" route cụ thể
$routes->get('products/(:num)', 'ProductController::detail/$1');
$routes->get('products/featured', 'ProductController::featured');
13. Debug route
CodeIgniter 4 cung cấp lệnh Spark để liệt kê toàn bộ route đã đăng ký:
php spark routes
Kết quả sẽ hiển thị method, route, handler và filter (nếu có), giúp bạn kiểm tra nhanh cấu hình routing của mình.
14. Một số lưu ý quan trọng
- Luôn đặt các route cụ thể trước các route động để tránh bị "nuốt" route.
- Sử dụng named routes thay vì hard-code URL để dễ bảo trì khi thay đổi cấu trúc.
- Nhóm route theo module (admin, api, auth...) để code gọn gàng và dễ quản lý.
- Áp dụng filter cho các route cần bảo vệ, đặc biệt là các route admin.
- Hạn chế dùng
(:any)vì có thể gây xung đột với các route khác. - Kiểm tra route thường xuyên bằng
php spark routesđể phát hiện lỗi sớm.
15. Kết luận
Routing trong CodeIgniter 4 vừa mạnh mẽ vừa linh hoạt, đủ sức đáp ứng từ những dự án nhỏ đến các hệ thống lớn với hàng trăm route. Việc nắm vững routing giúp bạn kiểm soát hoàn toàn cấu trúc URL, tăng tính bảo mật và cải thiện trải nghiệm người dùng. Hãy bắt đầu từ những route cơ bản, sau đó dần áp dụng các kỹ thuật nâng cao như group, filter, named route và resource để xây dựng ứng dụng chuyên nghiệp hơn.
Chúc bạn áp dụng thành công routing vào dự án CodeIgniter 4 của mình!

