Mặc định cakePHP framework đã build sẵn, có thể tự động matching url mà không cần khai báo route. Điều này chúng ta đã biết khi tìm hiểu về cakephp conventions. Ngoài ra, cakePHP cũng cho phép chúng ta tự khai báo route. Hôm nay chúng ta cùng tìm hiểu về cakePHP routing nhé.
Các routing được định nghĩa trong file config/routes.php
. Cakephp 4 sử dụng class Cake\Routing\RouterBuilder
để mapping URL với controller action. Định nghĩa 1 route lấy tất cả các bài viết
$routes->connect('/articles', ['controller' => 'Articles', 'action' => 'index']);
Giờ khi truy cập vào url {domain}/articles
sẽ mapping đến method index trong controller Articles.
1. Truyền tham số cho action
// routes.php
$routes->connect(
'/articles/{id}',
['controller' => 'Articles', 'action' => 'view']
)
->setPass(['id'])
->setPatterns([
'id' => '\d+',
]);
// Viết ngắn ngọn hơn
$routes->connect(
'/articles/{id}',
['controller' => 'Articles', 'action' => 'view'],
['id' => '\d+', 'pass' => ['id']]
);
// src/Controller/ArticlesController.php
public function view($id = null)
{
// Some code here...
}
Với khai báo trên ta đã validate {id} trên url bắt buộc phải là số, khi truy cập vào url /articles/{id}
mapping với controller Articles action view và tham số id trên url sẽ là đối số $id của action view.
2. Đặt tên cho route
// Đặt tên cho route dùng hàm connect.
$routes->connect(
'/login',
['controller' => 'Members', 'action' => 'login'],
['_name' => 'login']
);
// Đặt tên khi sử dụng specific route
$routes->post(
'/logout',
['controller' => 'Members', 'action' => 'logout'],
'logout'
);
3. Định nghĩa route theo group
Để group các route lại với nhau cakePHP sử dụng hàm scope()
. Việc gom nhóm giúp không bị lặp code
// Code chưa gom nhóm
$routes->connect('/articles', ['controller' => 'Articles', 'action' => 'index']);
$routes->connect(
'/articles/{id}',
['controller' => 'Articles', 'action' => 'view'],
['id' => '\d+', 'pass' => ['id']]
);
// Code đã gom nhóm
$routes->scope('/articles', function (RouteBuilder $routes) {
$routes->connect('/', ['controller' => 'Articles', 'action' => 'index']);
$routes->connect(
'/{id}',
['controller' => 'Articles', 'action' => 'view'],
['id' => '\d+', 'pass' => ['id']]
);
})
// Gom nhóm và set sub namespace cho controller
$routes->scope('/admins', ['prefix' => 'Admins'], function (RouteBuilder $routes) {
$routes->scope('/articles', function (RouteBuilder $routes) {
$routes->connect('/', ['controller' => 'Articles', 'action' => 'index']);
$routes->connect(
'/{id}',
['controller' => 'Articles', 'action' => 'view'],
['id' => '\d+', 'pass' => ['id']]
);
})
})
4. Matching Specific HTTP Methods
Phần này giúp giới hạn http request đến controller action, có thể chỉ cho phép 1 phương thức HTTP hoặc nhiều.
$routes->scope('/articles', function (RouteBuilder $routes) {
// route này cho mapping với POST request.
$routes->post(
'/',
['controller' => 'Articles', 'action' => 'store']
);
// route này cho mapping với POST hoặc PUT request.
$routes->connect(
'/{id}',
[
'controller' => 'Articles',
'action' => 'edit',
]
)->setMethods(['POST', 'PUT']);
});
5. Route middleware
Khi muốn sử dụng middleware trong 1 scope đầu tiên bạn cần đăng kí middleware đó.
use Cake\Http\Middleware\CsrfProtectionMiddleware;
use Cake\Http\Middleware\EncryptedCookieMiddleware;
$routes->scope('/', function (RouteBuilder $routes) {
$routes->registerMiddleware('csrf', new CsrfProtectionMiddleware());
$routes->registerMiddleware('cookies', new EncryptedCookieMiddleware());
});
Sau đó mới có thể sử dụng middleware
use Cake\Http\Middleware\CsrfProtectionMiddleware;
use Cake\Http\Middleware\EncryptedCookieMiddleware;
$routes->scope('/', function (RouteBuilder $routes) {
$routes->registerMiddleware('csrf', new CsrfProtectionMiddleware());
$routes->registerMiddleware('cookies', new EncryptedCookieMiddleware());
$routes->scope('/cms', function (RouteBuilder $routes) {
// Enable CSRF & cookies middleware
$routes->applyMiddleware('csrf', 'cookies');
$routes->get('/articles/{action}/*', ['controller' => 'Articles'])
});
});
// Gom nhóm middleware
$routes->registerMiddleware('cookie', new EncryptedCookieMiddleware());
$routes->registerMiddleware('auth', new AuthenticationMiddleware());
$routes->registerMiddleware('csrf', new CsrfProtectionMiddleware());
$routes->middlewareGroup('web', ['cookie', 'auth', 'csrf']);
// Apply the group
$routes->applyMiddleware('web');
6. RESTful Routing
Khai báo routing dùng cho restful api. Khi viết resfull api chúng ta sẽ rất hay sử dụng resource route, và cakePhp 4 cũng có luôn.
$routes->scope('/api', function (RouteBuilder $routes) {
$routes->setExtensions(['json']);
$routes->resources('articles');
});
Nhưng vậy là đã khai báo được resourec api cho controler Articles
/api/articles
/api/articles/{id}
7. Resource Routes
// Nested Resource Route
$routes->scope('/api', function (RouteBuilder $routes) {
$routes->resources('Articles', function (RouteBuilder $routes) {
$routes->resources('Comments');
});
});
// Mapching with url
/api/articles/{article_id}/comments
/api/articles/{article_id}/comments/{id}
// Định nghĩa thêm route cho Resource Route
$routes->resources('Articles', [
'map' => [
'deleteAll' => [
'action' => 'deleteAll',
'method' => 'DELETE'
]
]
]);
// This would connect /articles/deleteAll
// Giới hạn route resources
$routes->resources('Articles', [
'only' => ['index', 'view']
]);
8. Redirect Routing
$routes->scope('/', function (RouteBuilder $routes) {
$routes->redirect('/articles/*', 'https://google.com', ['status' => 302]);
});
Chia file route thành nhiều file nhỏ, tạo thư mục config/Routes
để gom nhóm các route cùng chức năng sau đó require vào file route
// Chia nhỏ file route
// Router api v1
if (file_exists(CONFIG . 'Routers/Api/version1.php')) {
require(CONFIG . 'Routers/Api/version1.php');
}
// Router api v2
if (file_exists(CONFIG . 'Routers/Api/version2.php')) {
require(CONFIG . 'Routers/Api/version2.php');
}
// Router admin
if (file_exists(CONFIG . 'Routers/admin.php')) {
require(CONFIG . 'Routers/admin.php');
}
Tạo file config/Routers/Api/version1.php
để định nghĩa các route cho api version 1
<?php
use Cake\Routing\Route\DashedRoute;
use Cake\Routing\RouteBuilder;
/** @var \Cake\Routing\RouteBuilder $routes */
$routes->setRouteClass(DashedRoute::class);
$routes->scope('/api/v1', ['prefix' => 'Api/V1'], function (RouteBuilder $routes) {
$routes->setExtensions(['json']);
// Devices
$routes->resources('Devices');
});
Tạo file config/Routers/admin.php
định nghĩa các route cho admin
<?php
use Cake\Http\Middleware\CsrfProtectionMiddleware;
use App\Middleware\BasicAuthMiddleware;
use Cake\Routing\Route\DashedRoute;
use Cake\Routing\RouteBuilder;
/** @var \Cake\Routing\RouteBuilder $routes */
$routes->setRouteClass(DashedRoute::class);
$routes->scope('/admin', ['prefix' => 'Admin'], function (RouteBuilder $routes) {
$csrf = new CsrfProtectionMiddleware([
'httponly' => true,
]);
$routes->registerMiddleware('csrf', $csrf);
$routes->registerMiddleware('basicAuth', new BasicAuthMiddleware());
$routes->middlewareGroup('web', ['csrf', 'basicAuth']);
$routes->applyMiddleware('web');
// Admins.
$routes->connect('/',
['controller' => 'Admins', 'action' => 'index'],
['_name' => 'admins.index']);
$routes->fallbacks();
});
Nếu bạn muốn tạo url thì dùng các phương thức sau
// Tạo link /articles/view/{$id}
$this->Html->link('View', '/articles/view/' . $id);
$this->Html->link(
'View',
['controller' => 'Articles', 'action' => 'view', $id]
);
// Tạo url /articles/index?page=1#top
$routes->url([
'controller' => 'Articles',
'action' => 'index',
'?' => ['page' => 1],
'#' => 'top'
]);
Như vậy là chúng ta đã tự định nghĩa route cho ứng dụng xong. Hi vọng bài viết giúp ích được cho bạn. Thanks for reading...