Định tuyến
Quy tắc mặc định của định tuyến
Quy tắc mặc định của webman là http://127.0.0.1:8787/{controller}/{action}.
Controller mặc định là app\controller\IndexController, action mặc định là index.
Ví dụ truy cập:
http://127.0.0.1:8787sẽ mặc định truy cập phương thứcindexcủa lớpapp\controller\IndexControllerhttp://127.0.0.1:8787/foosẽ mặc định truy cập phương thứcindexcủa lớpapp\controller\FooControllerhttp://127.0.0.1:8787/foo/testsẽ mặc định truy cập phương thứctestcủa lớpapp\controller\FooControllerhttp://127.0.0.1:8787/admin/foo/testsẽ mặc định truy cập phương thứctestcủa lớpapp\admin\controller\FooController(xem thêm Ứng dụng đa nhiệm)
Ngoài ra, từ phiên bản 1.4, webman hỗ trợ định tuyến mặc định phức tạp hơn, ví dụ:
app
├── admin
│ └── v1
│ └── v2
│ └── v3
│ └── controller
│ └── IndexController.php
└── controller
├── v1
│ └── IndexController.php
└── v2
└── v3
└── IndexController.php
Khi bạn muốn thay đổi định tuyến yêu cầu, hãy thay đổi tệp cấu hình config/route.php.
Nếu bạn muốn tắt định tuyến mặc định, hãy thêm cấu hình sau vào cuối tệp cấu hình config/route.php:
Route::disableDefaultRoute();
Định tuyến đóng
Thêm mã định tuyến sau vào tệp config/route.php:
use support\Request;
Route::any('/test', function (Request $request) {
return response('test');
});
Lưu ý
Do hàm đóng không thuộc bất kỳ controller nào, nên$request->app$request->controller$request->actionđều là chuỗi trống.
Khi truy cập địa chỉ http://127.0.0.1:8787/test, nó sẽ trả về chuỗi test.
Lưu ý
Đường dẫn định tuyến phải bắt đầu bằng/, ví dụ:
use support\Request;
// Sử dụng sai
Route::any('test', function (Request $request) {
return response('test');
});
// Sử dụng đúng
Route::any('/test', function (Request $request) {
return response('test');
});
Định tuyến lớp
Thêm mã định tuyến sau vào tệp config/route.php:
Route::any('/testclass', [app\controller\IndexController::class, 'test']);
Khi truy cập địa chỉ http://127.0.0.1:8787/testclass, nó sẽ trả về giá trị của phương thức test của lớp app\controller\IndexController.
Định tuyến bằng chú thích
Định nghĩa route qua chú thích trên phương thức điều khiển, không cần cấu hình trong config/route.php.
Lưu ý
Tính năng này yêu cầu webman-framework >= v2.2.0
Cách dùng cơ bản
namespace app\controller;
use support\annotation\route\DisableDefaultRoute;
use support\annotation\route\Get;
use support\annotation\route\Post;
use support\annotation\route\Route;
#[DisableDefaultRoute]
class UserController
{
#[Get('/user/{id}')]
public function show($id)
{
return "user $id";
}
#[Post('/user')]
public function store()
{
return 'created';
}
#[Route('/user/form', ['GET', 'POST'], 'user.form')]
public function form()
{
return 'form';
}
}
Chú thích khả dụng: #[Get] #[Post] #[Put] #[Delete] #[Patch] #[Head] #[Options] #[Any] (bất kỳ phương thức nào). Đường dẫn phải bắt đầu bằng /. Tham số thứ hai có thể chỉ định tên route, dùng cho route() khi tạo URL.
#[DisableDefaultRoute] tắt định tuyến mặc định của controller (tùy chọn); chỉ các route định nghĩa bằng chú thích mới truy cập được.
Cú pháp đầy đủ #[Route]: #[Route(path, methods, name)]
path: đường dẫn route, bắt đầu bằng/; khinullchỉ giới hạn phương thức HTTP của route mặc định mà không đăng ký route mớimethods: phương thức HTTP, chuỗi hoặc mảng chuỗi, vd.'GET'hoặc['GET','POST']name: tên route choroute('name')tạo URL, có thể bỏ qua
Chú thích không tham số: giới hạn phương thức HTTP của route mặc định
Không có đường dẫn thì chỉ giới hạn phương thức HTTP được phép cho hành động đó, vẫn dùng đường dẫn route mặc định:
#[Post]
public function create() { ... } // Chỉ cho phép POST, đường dẫn vẫn là /user/create
#[Get]
public function index() { ... } // Chỉ cho phép GET
Có thể kết hợp nhiều chú thích để cho phép nhiều phương thức:
#[Get]
#[Post]
public function form() { ... } // Cho phép GET và POST
Phương thức không khai báo trong chú thích sẽ trả về 405.
Nhiều chú thích có đường dẫn sẽ đăng ký thành các route độc lập: #[Get('/a')] #[Post('/b')] tạo route GET /a và POST /b.
Tiền tố nhóm route
Dùng #[RouteGroup] trên class để thêm tiền tố cho tất cả route của phương thức:
use support\annotation\route\RouteGroup;
use support\annotation\route\Get;
#[RouteGroup('/api/v1')]
class UserController
{
#[Get('/user/{id}')] // Đường dẫn thực tế /api/v1/user/{id}
public function show($id) { ... }
}
Phương thức HTTP tùy chỉnh và tên route
#[Route] hỗ trợ nhiều phương thức HTTP và tên route:
use support\annotation\route\Route;
#[Route('/user', ['GET', 'POST'], 'user.form')]
public function form() { ... }
// Chỉ đường dẫn và phương thức, không có tên route
#[Route('/user/update', 'PUT')]
public function update() { ... }
Tham số đường dẫn và regex
Đường dẫn route chú thích hỗ trợ cùng cú pháp tham số với config/route.php, bao gồm regex và tham số tùy chọn:
#[Get('/user/{id:\d+}')] // Chỉ id số
public function show($id) { ... }
#[Get('/user[/{name}]')] // name tùy chọn: /user hoặc /user/xxx
public function list($name = null) { ... }
#[Any('/user/[{path:.+}]')] // Khớp /user và /user/ với bất kỳ hậu tố nào
public function catchAll($path = null) { ... }
Xem mục 「Tham số của định tuyến」 trong tài liệu này.
Middleware
#[Middleware] trên controller hoặc method áp dụng cho route chú thích; cách dùng giống support\annotation\Middleware:
use support\annotation\Middleware;
#[Middleware(\app\middleware\AuthMiddleware::class)]
class UserController { ... }
#[Get('/user/{id}')]
#[Middleware(\app\middleware\RateLimitMiddleware::class)]
public function show($id) { ... }
Tạo URL với route()
Khi tên route được chỉ định trong chú thích, dùng route('name', $params) để tạo URL:
#[Get('/user/{id}', 'user.show')]
public function show($id) { ... }
// Sử dụng: route('user.show', ['id' => 123]) => /user/123
Tham số của định tuyến
Nếu có tham số trong định tuyến, sử dụng {key} để khớp, kết quả khớp sẽ được chuyển đến các tham số của phương thức điều khiển tương ứng (bắt đầu từ tham số thứ hai), ví dụ:
// Khớp với /user/123 /user/abc
Route::any('/user/{id}', [app\controller\UserController::class, 'get']);
namespace app\controller;
use support\Request;
class UserController
{
public function get(Request $request, $id)
{
return response('Nhận được tham số'.$id);
}
}
Nhiều ví dụ khác:
use support\Request;
// Khớp với /user/123, không khớp với /user/abc
Route::any('/user/{id:\d+}', function (Request $request, $id) {
return response($id);
});
// Khớp với /user/foobar, không khớp với /user/foo/bar
Route::any('/user/{name}', function (Request $request, $name) {
return response($name);
});
// Khớp với /user /user/123 và /user/abc [] biểu thị tùy chọn
Route::any('/user[/{name}]', function (Request $request, $name = null) {
return response($name ?? 'tom');
});
// Khớp mọi yêu cầu có tiền tố /user/
Route::any('/user/[{path:.+}]', function (Request $request) {
return $request->path();
});
// Khớp với tất cả các yêu cầu options : dùng để chỉ định regex
Route::options('[{path:.+}]', function () {
return response('');
});
Tóm tắt sử dụng nâng cao
Cú pháp
[]trong route Webman chủ yếu dùng cho phần đường dẫn tùy chọn hoặc khớp route động; cho phép định nghĩa cấu trúc đường dẫn và quy tắc khớp phức tạp hơn
:dùng để chỉ định biểu thức chính quy
Nhóm định tuyến
Đôi khi định tuyến bao gồm một số tiền tố giống nhau, trong trường hợp này, chúng ta có thể sử dụng nhóm định tuyến để đơn giản hóa định nghĩa. Ví dụ:
Route::group('/blog', function () {
Route::any('/create', function (Request $request) {return response('create');});
Route::any('/edit', function (Request $request) {return response('edit');});
Route::any('/view/{id}', function (Request $request, $id) {return response("view $id");});
});
Tương đương với
Route::any('/blog/create', function (Request $request) {return response('create');});
Route::any('/blog/edit', function (Request $request) {return response('edit');});
Route::any('/blog/view/{id}', function (Request $request, $id) {return response("view $id");});
Sử dụng nhóm lồng
Route::group('/blog', function () {
Route::group('/v1', function () {
Route::any('/create', function (Request $request) {return response('create');});
Route::any('/edit', function (Request $request) {return response('edit');});
Route::any('/view/{id}', function (Request $request, $id) {return response("view $id");});
});
});
Middleware (Phần Middleware)
Chúng ta có thể thiết lập middleware cho một hoặc một nhóm routes.
Ví dụ:
Route::any('/admin', [app\admin\controller\IndexController::class, 'index'])->middleware([
app\middleware\MiddlewareA::class,
app\middleware\MiddlewareB::class,
]);
Route::group('/blog', function () {
Route::any('/create', function () {return response('create');});
Route::any('/edit', function () {return response('edit');});
Route::any('/view/{id}', function ($request, $id) {return response("view $id");});
})->middleware([
app\middleware\MiddlewareA::class,
app\middleware\MiddlewareB::class,
]);
Ví dụ sử dụng sai (đúng khi webman-framework >= 1.5.7)
Route::group('/blog', function () {
Route::group('/v1', function () {
Route::any('/create', function (Request $request) {return response('create');});
Route::any('/edit', function (Request $request) {return response('edit');});
Route::any('/view/{id}', function (Request $request, $id) {return response("view $id");});
});
})->middleware([
app\middleware\MiddlewareA::class,
app\middleware\MiddlewareB::class,
]);
Ví dụ sử dụng đúng
Route::group('/blog', function () {
Route::group('/v1', function () {
Route::any('/create', function (Request $request) {return response('create');});
Route::any('/edit', function (Request $request) {return response('edit');});
Route::any('/view/{id}', function (Request $request, $id) {return response("view $id");});
})->middleware([
app\middleware\MiddlewareA::class,
app\middleware\MiddlewareB::class,
]);
});
Routes tài nguyên
Route::resource('/test', app\controller\IndexController::class);
// Xác định routes tài nguyên
Route::resource('/test', app\controller\IndexController::class, ['index','create']);
// Routes tài nguyên không xác định
// Ví dụ như khi truy cập notify, địa chỉ có thể là /test/notify hoặc /test/notify/{id} đều có thể, routeName sẽ là test.notify
Route::resource('/test', app\controller\IndexController::class, ['index','create','notify']);
| Phương Thức | URI | Hành Động | Tên Route |
|---|---|---|---|
| GET | /test | index | test.index |
| GET | /test/create | create | test.create |
| POST | /test | store | test.store |
| GET | /test/{id} | show | test.show |
| GET | /test/{id}/edit | edit | test.edit |
| PUT | /test/{id} | update | test.update |
| DELETE | /test/{id} | destroy | test.destroy |
| PUT | /test/{id}/recovery | recovery | test.recovery |
Tạo URL
Lưu ý:
Hiện tại không hỗ trợ việc tạo URL cho nhóm routes lồng nhau
Ví dụ về routes:
Route::any('/blog/{id}', [app\controller\BlogController::class, 'view'])->name('blog.view');
Chúng ta có thể sử dụng phương thức sau để tạo URL cho route này.
route('blog.view', ['id' => 100]); // Kết quả sẽ là /blog/100
Khi sử dụng URL của route trong view, phương pháp này có thể giúp tạo URL tự động mà không cần sửa đổi file view vì thay đổi trong các quy tắc route, để tránh việc phải thay đổi nhiều file view.
Lấy thông tin về route
Chúng ta có thể lấy thông tin của route hiện tại thông qua đối tượng $request->route, ví dụ:
$route = $request->route; // Tương đương với $route = request()->route;
if ($route) {
var_export($route->getPath());
var_export($route->getMethods());
var_export($route->getName());
var_export($route->getMiddleware());
var_export($route->getCallback());
var_export($route->param());
}
Lưu ý
Nếu request hiện tại không khớp với bất kỳ route nào được xác định trongconfig/route.php, thì$request->routesẽ là null, nghĩa là khi sử dụng route mặc định,$request->routesẽ là null.
Xử lý lỗi 404
Khi không tìm thấy route, webman mặc định sẽ trả về mã trạng thái 404 và xuất nội dung 404 tương ứng.
Nếu nhà phát triển muốn can thiệp vào quy trình kinh doanh khi không tìm thấy route, có thể sử dụng phương thức fallback của webman Route::fallback($callback). Ví dụ: logic dưới đây sẽ chuyển hướng về trang chủ khi không tìm thấy route.
Route::fallback(function(){
return redirect('/');
});
Hoặc khi không tìm thấy route sẽ trả về một dữ liệu json, điều này rất hữu ích khi webman hoạt động như một API.
Route::fallback(function(){
return json(['code' => 404, 'msg' => '404 not found']);
});
Thêm middleware cho 404
Mặc định các yêu cầu 404 không đi qua bất kỳ middleware nào. Nếu cần thêm middleware cho yêu cầu 404, tham khảo mã sau:
Route::fallback(function(){
return json(['code' => 404, 'msg' => '404 not found']);
})->middleware([
app\middleware\MiddlewareA::class,
app\middleware\MiddlewareB::class,
]);
Xem thêm: Trang Lỗi Tùy Chỉnh
Vô hiệu hóa route mặc định
// Vô hiệu hóa route mặc định của dự án chính, không ảnh hưởng plugin
Route::disableDefaultRoute();
// Vô hiệu hóa route admin của dự án chính, không ảnh hưởng plugin
Route::disableDefaultRoute('', 'admin');
// Vô hiệu hóa route mặc định của plugin foo, không ảnh hưởng dự án chính
Route::disableDefaultRoute('foo');
// Vô hiệu hóa route admin của plugin foo, không ảnh hưởng dự án chính
Route::disableDefaultRoute('foo', 'admin');
// Vô hiệu hóa route mặc định của controller [\app\controller\IndexController::class, 'index']
Route::disableDefaultRoute([\app\controller\IndexController::class, 'index']);
Chú thích vô hiệu hóa route mặc định
Chúng ta có thể dùng chú thích để vô hiệu hóa route mặc định của một controller:
namespace app\controller;
use support\annotation\DisableDefaultRoute;
#[DisableDefaultRoute]
class IndexController
{
public function index()
{
return 'index';
}
}
Tương tự, cũng có thể dùng chú thích để vô hiệu hóa route mặc định của phương thức controller:
namespace app\controller;
use support\annotation\DisableDefaultRoute;
class IndexController
{
#[DisableDefaultRoute]
public function index()
{
return 'index';
}
}
Giao Diện Người Dùng Route
// Thiết lập route cho tất cả các phương thức của $uri
Route::any($uri, $callback);
// Thiết lập route GET cho $uri
Route::get($uri, $callback);
// Thiết lập route POST cho $uri
Route::post($uri, $callback);
// Thiết lập route PUT cho $uri
Route::put($uri, $callback);
// Thiết lập route PATCH cho $uri
Route::patch($uri, $callback);
// Thiết lập route DELETE cho $uri
Route::delete($uri, $callback);
// Thiết lập route HEAD cho $uri
Route::head($uri, $callback);
// Thiết lập route OPTIONS cho $uri
Route::options($uri, $callback);
// Thiết lập nhiều loại route cùng một lúc
Route::add(['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'], $uri, $callback);
// Route nhóm
Route::group($path, $callback);
// Route tài nguyên
Route::resource($path, $callback, [$options]);
// Vô hiệu hóa route mặc định
Route::disableDefaultRoute($plugin = '');
// Fallback route, thiết lập route mặc định
Route::fallback($callback, $plugin = '');
// Lấy tất cả thông tin route
Route::getRoutes();
Nếu không tìm thấy route cho $uri (bao gồm route mặc định), và fallback route cũng không được thiết lập, webman sẽ trả về 404.
Tập tin cấu hình đa tuyến
Nếu bạn muốn quản lý tuyến đường bằng cách sử dụng nhiều tập tin cấu hình tuyến đường, ví dụ như ứng dụng đa khi mỗi ứng dụng có cấu hình tuyến đường riêng của mình, lúc này bạn có thể tải các tập tin cấu hình tuyến đường bên ngoài thông qua require.
Ví dụ trong config/route.php:
<?php
// Tải tập tin cấu hình tuyến đường của ứng dụng admin
require_once app_path('admin/config/route.php');
// Tải tập tin cấu hình tuyến đường của ứng dụng api
require_once app_path('api/config/route.php');