URL与控制器 - 自定义路由

优质
小牛编辑
139浏览
2023-12-01

自定义路由

easySwoole支持路由拦截。其路由利用fastRoute实现,因此其路由规则与其保持一致,该组件的详细文档请参考 GitHub文档

路由定义

若需要再easySwoole使用路由拦截功能,请在应用目录(默认为App)下,建立Router类,井继承Core\AbstractInterface\AbstractRouter实现addRouter方法,如果在类UNIX系统下请严格注意文件名的大小写,如果获取不到该类则会跳过路由检测,进行框架内置的URL解析

基本路由示例

定义一个路由非常简单,只需要在App\Router.php添加如下代码

  1. <?php
  2. namespace App;
  3. use Core\AbstractInterface\AbstractRouter;
  4. use Core\Http\Response;
  5. use FastRoute\RouteCollector;
  6. class Router extends AbstractRouter
  7. {
  8. function addRouter(RouteCollector $routeCollector)
  9. {
  10. // 路由到控制器 http://localhost:9501/router
  11. $routeCollector->addRoute('GET', '/router', '/Index');
  12. // 路由到闭包 http://localhost:9501/router2
  13. $routeCollector->addRoute('GET', '/router2', function () {
  14. $Response = Response::getInstance();
  15. $Response->write('Hello esRouter!');
  16. $Response->end();
  17. });
  18. }
  19. }

注意:若在路由回调函数中不结束该请求响应,则该次请求将会继续进行Dispatch并尝试寻找对应的控制器进行响应处理。

addRoute方法

定义路由的addRoute方法原型如下,该方法需要三个参数,下面围绕这三个参数我们对路由组件进行更深一步的了解

  1. $routeCollector->addRoute($httpMethod, $routePattern, $handler)

httpMethod


该参数需要传入一个大写的HTTP方法字符串,指定路由可以拦截的方法,单个方法直接传入字符串,需要拦截多个方法可以传入一个一维数组,如下面的例子:

  1. // 拦截GET方法
  2. $routeCollector->addRoute('GET', '/router', '/Index');
  3. // 拦截POST方法
  4. $routeCollector->addRoute('POST', '/router', '/Index');
  5. // 拦截多个方法
  6. $routeCollector->addRoute(['GET', 'POST'], '/router', '/Index');

routePattern


传入一个路由匹配表达式,符合该表达式要求的路由才会被拦截并进行处理,表达式支持{参数名称:匹配规则}这样的占位符匹配,用于限定路由参数

基本匹配

下面的定义将会匹配 http://localhost:9501/users/info

  1. $routeCollector->addRoute('GET', '/users/info', 'handler');

绑定参数

下面的定义将/users/后面的部分作为参数,并且限定参数只能是数字[0-9]

  1. // 可以匹配: http://localhost:9501/users/12667
  2. // 不能匹配: http://localhost:9501/users/abcde
  3. $routeCollector->addRoute('GET', '/users/{id:\d+}', 'handler');

下面的定义不做任何限定,仅将匹配到的URL部分获取为参数

  1. // 可以匹配: http://localhost:9501/users/12667
  2. // 可以匹配: http://localhost:9501/users/abcde
  3. $routeCollector->addRoute('GET', '/users/{name}', 'handler');

有时候路由的部分位置是可选的,可以像下面这样定义

  1. // 可以匹配: http://localhost:9501/users/to
  2. // 可以匹配: http://localhost:9501/users/to/username
  3. $routeCollector->addRoute('GET', '/users/to[/{name}]', 'handler');

获取路由中绑定的参数有两种情况

  1. handler传入了一个闭包,Dispatch会将绑定的参数按顺序传给闭包
  2. handler传入了一个控制器路径,Dispatch会将绑定的参数附加给Request对象

利用该方法还可以实现请求/router/fun1/{id:\d+}但是符合一定条件的请求需要分发给/router/fun2/{id:\d+}处理的情况

  1. // 在闭包中使用
  2. $routeCollector->addRoute('GET', '/router/{id:\d+}', function ($id) {
  3. $Response = Response::getInstance();
  4. $Response->write('Userid : ' . $id);
  5. $Response->end();
  6. });
  7. // --------------------------------------------------------
  8. // 直接调用控制器方法
  9. $routeCollector->addRoute('POST', '/router/{id:\d+}', '/Index');
  10. // 此时可以在控制器中调用Request对象存放的参数
  11. $id = $this->request()->getQueryParam('id');
  12. // --------------------------------------------------------
  13. // 绑定参数并跳转到控制器
  14. $routeCollector->addRoute('GET', '/router2/{id:\d+}', function ($id) {
  15. // 将请求参数附加到Request
  16. Request::getInstance()->withQueryParams(['id' => $id]);
  17. // 按自己的处理逻辑转发请求给控制器
  18. Response::getInstance()->forward('/Index');
  19. });

handler


指定路由匹配成功后需要处理的方法,可以传入一个闭包,当传入闭包时一定要注意处理完成之后要处理结束响应否则请求会继续Dispatch寻找对应的控制器来处理,当然如果利用这一点,也可以对某些请求进行处理后再交给控制器执行逻辑

  1. // 传入闭包的情况
  2. $routeCollector->addRoute('GET', '/router/{id:\d+}', function ($id) {
  3. $Response = Response::getInstance();
  4. $Response->write('Userid : ' . $id);
  5. $Response->end();
  6. });

也可以直接传入控制器路径

  1. $routeCollector->addRoute('GET', '/router2/{id:\d+}', '/Index');