路由
默認(rèn)路由規(guī)則
webman默認(rèn)路由規(guī)則是 http://127.0.0.1:8787/{控制器}/{動作}
。
默認(rèn)控制器為app\controller\IndexController
,默認(rèn)動作為index
。
例如訪問:
http://127.0.0.1:8787
將默認(rèn)訪問app\controller\IndexController
類的index
方法http://127.0.0.1:8787/foo
將默認(rèn)訪問app\controller\FooController
類的index
方法http://127.0.0.1:8787/foo/test
將默認(rèn)訪問app\controller\FooController
類的test
方法http://127.0.0.1:8787/admin/foo/test
將默認(rèn)訪問app\admin\controller\FooController
類的test
方法 (參考多應(yīng)用)
另外webman從1.4開始支持更復(fù)雜的默認(rèn)路由,例如
app
├── admin
│ └── v1
│ └── v2
│ └── v3
│ └── controller
│ └── IndexController.php
└── controller
├── v1
│ └── IndexController.php
└── v2
└── v3
└── IndexController.php
當(dāng)您想改變某個(gè)請求路由時(shí)請更改配置文件 config/route.php
。
如果你想關(guān)閉默認(rèn)路由,在配置文件 config/route.php
里最后一行加上如下配置:
Route::disableDefaultRoute();
閉包路由
config/route.php
里添加如下路由代碼
use support\Request;
Route::any('/test', function (Request $request) {
return response('test');
});
注意
由于閉包函數(shù)不屬于任何控制器,所以$request->app
$request->controller
$request->action
全部為空字符串。
當(dāng)訪問地址為 http://127.0.0.1:8787/test
時(shí),將返回test
字符串。
注意
路由路徑必須以/
開頭,例如
use support\Request;
// 錯(cuò)誤的用法
Route::any('test', function (Request $request) {
return response('test');
});
// 正確的用法
Route::any('/test', function (Request $request) {
return response('test');
});
類路由
config/route.php
里添加如下路由代碼
Route::any('/testclass', [app\controller\IndexController::class, 'test']);
當(dāng)訪問地址為 http://127.0.0.1:8787/testclass
時(shí),將返回app\controller\IndexController
類的test
方法的返回值。
路由參數(shù)
如果路由中存在參數(shù),通過{key}
來匹配,匹配結(jié)果將傳遞到對應(yīng)的控制器方法參數(shù)中(從第二個(gè)參數(shù)開始依次傳遞),例如:
// 匹配 /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('接收到參數(shù)'.$id);
}
}
更多例子:
use support\Request;
// 匹配 /user/123, 不匹配 /user/abc
Route::any('/user/{id:\d+}', function (Request $request, $id) {
return response($id);
});
// 匹配 /user/foobar, 不匹配 /user/foo/bar
Route::any('/user/{name}', function (Request $request, $name) {
return response($name);
});
// 匹配 /user /user/123 和 /user/abc []表示可選
Route::any('/user[/{name}]', function (Request $request, $name = null) {
return response($name ?? 'tom');
});
// 匹配 任意以/user/為前綴的請求
Route::any('/user/[{path:.+}]', function (Request $request) {
return $request->path();
});
// 匹配所有options請求 :后填寫正則表達(dá)式,表示此命名參數(shù)的正則規(guī)則
Route::options('[{path:.+}]', function () {
return response('');
});
進(jìn)階用法總結(jié)
[]
語法在 Webman 路由中主要用于處理可選路徑部分或匹配動態(tài)路由,它讓你能夠?yàn)槁酚啥x更復(fù)雜的路徑結(jié)構(gòu)和匹配規(guī)則
:用于指定正則表達(dá)式
路由分組
有時(shí)候路由包含了大量相同的前綴,這時(shí)候我們可以用路由分組來簡化定義。例如:
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");});
});
等價(jià)與
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");});
group嵌套使用
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");});
});
});
路由中間件
我們可以給某個(gè)一個(gè)或某一組路由設(shè)置中間件。
例如:
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) {response("view $id");});
})->middleware([
app\middleware\MiddlewareA::class,
app\middleware\MiddlewareB::class,
]);
# 錯(cuò)誤使用例子 (webman-framework >= 1.5.7 時(shí)此用法有效)
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,
]);
# 正確使用例子
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,
]);
});
資源型路由
Route::resource('/test', app\controller\IndexController::class);
//指定資源路由
Route::resource('/test', app\controller\IndexController::class, ['index','create']);
//非定義性資源路由
// 如 notify 訪問地址則為any型路由 /test/notify或/test/notify/{id} 都可 routeName為 test.notify
Route::resource('/test', app\controller\IndexController::class, ['index','create','notify']);
Verb | URI | Action | Route Name |
---|---|---|---|
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 |
url生成
注意
暫時(shí)不支持group嵌套的路由生成url
例如路由:
Route::any('/blog/{id}', [app\controller\BlogController::class, 'view'])->name('blog.view');
我們可以使用如下方法生成這個(gè)路由的url。
route('blog.view', ['id' => 100]); // 結(jié)果為 /blog/100
視圖里使用路由的url時(shí)可以使用此方法,這樣不管路由規(guī)則如何變化,url都會自動生成,避免因路由地址調(diào)整導(dǎo)致大量更改視圖文件的情況。
獲取路由信息
通過$request->route
對象我們可以獲取當(dāng)前請求路由信息,例如
$route = $request->route; // 等價(jià)與 $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());
}
注意
如果當(dāng)前請求沒有匹配到config/route.php中配置的任何路由,則$request->route
為null,也就是說走默認(rèn)路由時(shí)$request->route
為null
處理404
當(dāng)路由找不到時(shí)默認(rèn)返回404狀態(tài)碼并輸出404相關(guān)內(nèi)容。
如果開發(fā)者想介入路由未找到時(shí)的業(yè)務(wù)流程,可以使用webman提供的回退路由Route::fallback($callback)
方法。比如下面的代碼邏輯是當(dāng)路由未找到時(shí)重定向到首頁。
Route::fallback(function(){
return redirect('/');
});
再比如當(dāng)路由不存在時(shí)返回一個(gè)json數(shù)據(jù),這在webman作為api接口時(shí)非常實(shí)用。
Route::fallback(function(){
return json(['code' => 404, 'msg' => '404 not found']);
});
給404添加中間件
默認(rèn)404請求不會走任何中間件,如果需要給404請求添加中間件,請參考以下代碼。
Route::fallback(function(){
return json(['code' => 404, 'msg' => '404 not found']);
})->middleware([
app\middleware\MiddlewareA::class,
app\middleware\MiddlewareB::class,
]);
相關(guān)鏈接 自定義404 500頁面
禁用默認(rèn)路由
// 禁用主項(xiàng)目默認(rèn)路由,不影響應(yīng)用插件
Route::disableDefaultRoute();
// 禁用主項(xiàng)目的admin應(yīng)用的路由,不影響應(yīng)用插件
Route::disableDefaultRoute('', 'admin');
// 禁用foo插件的默認(rèn)路由,不影響主項(xiàng)目
Route::disableDefaultRoute('foo');
// 禁用foo插件的admin應(yīng)用的默認(rèn)路由,不影響主項(xiàng)目
Route::disableDefaultRoute('foo', 'admin');
// 禁用控制器 [\app\controller\IndexController::class, 'index'] 的默認(rèn)路由
Route::disableDefaultRoute([\app\controller\IndexController::class, 'index']);
注解禁用默認(rèn)路由
我們可以通過注解禁用某個(gè)控制器的默認(rèn)路由,例如:
namespace app\controller;
use support\annotation\DisableDefaultRoute;
#[DisableDefaultRoute]
class IndexController
{
public function index()
{
return 'index';
}
}
同樣的,我們也可以通過注解禁用某個(gè)控制器的默認(rèn)路由,例如:
namespace app\controller;
use support\annotation\DisableDefaultRoute;
class IndexController
{
#[DisableDefaultRoute]
public function index()
{
return 'index';
}
}
路由接口
// 設(shè)置$uri的任意方法請求的路由
Route::any($uri, $callback);
// 設(shè)置$uri的get請求的路由
Route::get($uri, $callback);
// 設(shè)置$uri的post請求的路由
Route::post($uri, $callback);
// 設(shè)置$uri的put請求的路由
Route::put($uri, $callback);
// 設(shè)置$uri的patch請求的路由
Route::patch($uri, $callback);
// 設(shè)置$uri的delete請求的路由
Route::delete($uri, $callback);
// 設(shè)置$uri的head請求的路由
Route::head($uri, $callback);
// 設(shè)置$uri的options請求的路由
Route::options($uri, $callback);
// 同時(shí)設(shè)置多種請求類型的路由
Route::add(['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'], $uri, $callback);
// 分組路由
Route::group($path, $callback);
// 資源路由
Route::resource($path, $callback, [$options]);
// 禁用路由
Route::disableDefaultRoute($plugin = '');
// 回退路由,設(shè)置默認(rèn)的路由兜底
Route::fallback($callback, $plugin = '');
// 獲取所有路由信息
Route::getRoutes();
如果uri沒有對應(yīng)的路由(包括默認(rèn)路由),且回退路由也未設(shè)置,則會返回404。
多個(gè)路由配置文件
如果你想使用多個(gè)路由配置文件對路由進(jìn)行管理,例如多應(yīng)用時(shí)每個(gè)應(yīng)用下有自己的路由配置,這時(shí)可以通過require
外部文件的方式加載外部路由配置文件。
例如config/route.php
中
<?php
// 加載admin應(yīng)用下的路由配置
require_once app_path('admin/config/route.php');
// 加載api應(yīng)用下的路由配置
require_once app_path('api/config/route.php');