蛋白质 / 路由
简单快捷的URL路由器
Requires
- php: ^7.2
- proteins/event: ^1.0.0
- proteins/extensions: ^1.0.0
- proteins/filter: ^1.0.0
- proteins/options: ^1.0.0
- proteins/request: ^1.0.0
- proteins/response: ^1.0.0
- proteins/url: ^1.0.0
README
蛋白质 | 路由
简单快捷的URL路由器
安装
composer require proteins/route
通过
use Proteins\Route;
URL映射
您可以通过on
方法定义路由。
Route::on('/hello',function(){ echo 'Hello, Friend!'; });
这是定义响应于URL /hello
的HTTP GET
路由的最简单形式。
您可以使用流畅的API接口将相同的路由映射到多个请求方法。
Route::on('/hello') ->via('get','post') ->with(function(){ echo 'Hello, Friend!'; });
via
方法接受一个字符串数组,用于处理HTTP请求方法。
with
方法将可调用的函数绑定到路由。
如果您需要将不同的HTTP方法映射到单个URL的不同回调(例如通过REST API公开资源),则map
方法允许您传递一个method
=> callback
字典。
Route::map('/entity(/:id)/?',[ 'get' => function($id=null){ // READ: fetch the $id element or all if $id === null }, 'post' => function($id=null){ // CREATE: build a new element }, 'put' => function($id=null){ // UPDATE: modify $id element's properties }, 'delete' => function($id=null){ // DELETE: delete $id element }, ])
any
简写会触发响应于URL /hello
的任何HTTP动词的路由。
Route::any('/hello',function(){ echo 'Hello, World!'; });
这等同于做
Route::on('/hello') ->via('*') ->with(function(){ echo 'Hello, World!'; });
URL模式匹配和参数提取
路由模式本质上是一个正则表达式,有一些细微的差别。
模式将始终与REQUEST_URI
参数的end
部分匹配(已移除查询字符串)。
规则
- 每个
(...)
组都是可选的 - 您可以通过
:named_parameter
提取参数 - 模式不能包含
#
字符
示例
Route::on('/element(/:id)/?',function($id=null){ if (null === $id){ $result = get_all_elements(); } else { $result = get_element_by_id($id); } print_r($result); });
在这个示例中,可选的(在(...)
组中):id
在存在时被提取,并且路由可以可选地通过/
结束。
此路由处理以下所有请求
/element
/element/
/element/123
/element/123/
/element/1919191
/element/462635
- 等等。
但是,如您所见,此示例还处理了/element/fooo
。如果我们想给提取的参数提供格式规则,我们可以使用rules
方法。
rules
方法接受一个named_parameter
=> regex
字典。
rules([ 'parameter_name' => 'parameter_regex_pattern' ])
我们可以在前面的示例中为接受仅整数值(由正则表达式模式\d+定义)的id
参数添加规则。
示例
Route::on('/element(/:id)/?',function($id=null){ if (null === $id){ $result = get_all_elements(); } else { $result = get_element_by_id($id); } print_r($result); }) ->rules([ 'id' => '\d+' ]);
路由分组
您可以根据前缀模式封装路由。如果当前请求不匹配组URL模式,则不会注册相对路由定义。
注意:此行为受
core.route.pruning
标志控制。
此功能可用于响应时间优化和将路由树挂载到动态URL前缀。
您可以定义多个嵌套路由组。
示例
管理部分
Route::group('/admin',function(){ Route::on('/',function(){ echo "Admin Index"; }); Route::on('/login') ->via('get','post') ->with(function(){ // Handle login }); Route::on('/logout',function(){ // handle logout }); Route::group('/dashboard',function(){ Route::on('/',function(){ // Dashboard }); Route::on('/details',function(){ // Dashboard Details }); }); });
带有动态参数的路由组
路由组可以有动态参数,这些参数将与正常路由一样被提取。
Route::group("/book/:id", function($id){ $book = new Book($id); Route::on("/", function() use ($book){ return $book; }); Route::on("/:field", function($field) use ($book){ return $book->$field; }); });
路由中间件
您可以在路由或路由组之前和之后附加中间件列表。
如果中间件返回
false
,则整个路由执行将停止。
中间件可以链接,before
将按照反向声明顺序(FIFO)执行,after
将按照直接声明顺序(LIFO)执行。
Route::on('/', "[TEST]" ) ->before(function(){ echo "(B1)"; }) ->before(function(){ echo "(B2)"; }) ->after(function(){ echo "(A1)"; }) ->after(function(){ echo "(A2)"; });
输出如下
(B2)(B1)[TEST](A1)(A2)
您可以使用路由组一次性将中间件应用于多个路由
Route::group('/private',function(){ Route::on('/', ... ); Route::on('/dashboard', ... ); Route::on('/profile', ... ); Route::on('/settings', ... ); })->before(function(){ if ( ! user_authorized() ) { Response::error(403,"Forbidden"); return false; } });
分发路由
请记住在脚本结束之前调用dispatch
方法以执行路由。
Route::on('/hello',function(){ echo 'Hello, Friend!'; }); // Run the route dispatcher. Route::dispatch();
您可以重写请求URI和方法,通过将它们作为参数传递给dispatch方法。
Route::dispatch($URL=null, $method=null, $return_route=false)
示例
Route::dispatch('/my/forced/uri','OPTIONS');
如果匹配到(如果有)的路由,可以通过将true传递给return_route参数,而无需自动执行返回的路由。
$matched_route = Route::dispatch(null,null,true);
路由找不到匹配项。(HTTP 404)
当没有路由与当前请求匹配时,将触发404事件。
您可以将视图追加到Response中,以显示一个礼貌页面。
Event::on(404,function(){ Response::html( View::from('errors/404') ); });
渲染快捷方式
除了渲染回调之外,您还可以传递一个字符串或视图,以进行直接渲染。
闭包
Route::on('/',function(){ return View::from('index'); });
<h1>I'm the index!</h1>
一个View
Route::on('/', View::from('index') );
<h1>I'm the index!</h1>
一个字符串(不是一个可调用的字符串)
Route::on('/', 'Not a callable string' );
Not a callable string
一个对象
Route::on('/',(object)[ 'alpha' => 123, 'beta' => [1,2,3] ]);
{"alpha":123,"beta":[1,2,3]}
HTTP/2资源推送
您可以直接从路由和路由组定义中推送资源。
语法与Response::push方法相同方法。
Route::on('/', function() { return View::from('index'); })->push([ 'style' => '/assets/css/main.css', 'script' => [ '/assets/js/vendors.js', '/assets/js/main.js', ], ]);
URL标记和反向路由
您可以通过tag方法给路由添加一个名称标签。
Route::on('/user/:id', function ($id) { return "USER[$id]"; })->tag('user');
通过Route::tagged($name)方法检索命名路由。
$user_route = Route::tagged('user');
要获取路由的URL,请使用getURL($params = [])方法。
echo $user_route->getURL();
作为快捷方式,您还可以通过Route::URL($name, $params = [])助手获取命名路由的URL。
echo Route::URL('user');
/user
您还可以传递一个数组来映射和分配路由的动态值。
echo Route::URL('user',[ 'id' => 123, ]);
/user/123
注意: Route::URL方法的返回值是一个[[URL]]对象。
事件和过滤器
路由具有Events特质的行为,唯一的不同之处在于,Events::on方法被重命名为onEvent,以避免与Route::on处理器冲突。
Route::onEvent('start',function($route, $args, $method){ echo "Called route.\n"; });