当前位置: 首页 > 后端技术 > PHP

FastRoute-快速请求路由

时间:2023-03-30 02:03:00 PHP

链接https://github.com/nikic/Fast...这个库提供了一个基于正则表达式的快速路由实现。本文解释了FastRoute的工作原理以及它为什么很快。通过composer安装Installcomposerrequirenikic/fast-routerequirenikic/fast-routerequiresPHP5.4andabovetouse这是一个基本的用法示例addRoute('GET','/users','get_all_users_handler');//{id}必须是数字(\d+)$r->addRoute('GET','/user/{id:\d+}','get_user_handler');///{title}后缀可选$r->addRoute('GET','/articles/{id:\d+}[/{title}]','get_article_handler');});//获取请求的方法和URI$httpMethod=$_SERVER['REQUEST_METHOD'];$uri=$_SERVER['REQUEST_URI'];//删除查询字符串(后面是什么?)和解码的URIif(false!==$pos=strpos($uri,'?')){$uri=substr($uri,0,$pos);}$uri=rawurldecode($uri);$routeInfo=$dispatcher->dispatch($httpMethod,$uri);switch($routeInfo[0]){caseFastRoute\Dispatcher::NOT_FOUND://...404NotFound没有找到对应的方法break;caseFastRoute\Dispatcher::METHOD_NOT_ALLOWED:$allowedMethods=$routeInfo[1];//...405MethodNotAllowed该方法不允许中断;caseFastRoute\Dispatcher::FOUND://找到对应的方法$handler=$routeInfo[1];//获取处理函数$vars=$routeInfo[2];//获取请求参数//...用$vars调用$handler//调用处理器break;}定义路由作为参数通过在收集器实例中调用addRoute()添加路由。$r->addRoute($method,$routePattern,$handler);$method是一个大写的HTTP方法,可以通过路由匹配,可以使用数组指定多个有效的$method。//这里有两行调用$r->addRoute('GET','/test','handler');$r->addRoute('POST','/test','handler');//相当于这一行调用$r->addRoute(['GET','POST'],'/test','handler');默认情况下,$routePattern使用一种语法,例如{foo}是一个名为foo的帐户位字符,可以匹配正则表达式[^/]+..要调整占位符匹配的模式,您可以通过指定自定义模式写{bar:[0-9]+}。一些例子//匹配/user/42,不匹配/user/xyx$r->addRoute('GET','/user/{id:\d+}','handler');//匹配/user/foobar,不匹配/user/foo/bar$r->addRoute('GET','/user/{name}','handler');//匹配/user/foobar,也匹配/user/foo/bar$r->addRoute('GET','/user/{name:.+}','handler');路由占位符的自定义模式不能使用捕获组,比如{lang:(en|de)}不是Validplaceholders,因为()是捕获组,可以使用{lang:en|de}或者{lang:(?:en|de)}代替。此外,路由中定义的部分[...]是可选匹配项,因此/foo[bar]将同时匹配/foo和/foobar。路由可选部分只支持定义的末尾,中间不支持。//该路由有[/{name}]可选匹配部分$r->addRoute('GET','/user/{id:\d+}[/{name}]','handler');//是相当于这两条路由$r->addRoute('GET','/user/{id:\d+}','handler');$r->addRoute('GET','/user/{id:\d+}/{name}','handler');//也支持多层嵌套可选路由$r->addRoute('GET','/user[/{id:\d+}[/{name}]]','handler');//此路由定义无效,因为可选部分只能在定义的末尾$r->addRoute('GET','/user[/{id:\d+}]/{名称}','处理程序');$handler参数不一定非要是回调函数,它也可以是控制器类名或任何其他类型的数据。FastRoute只告诉你哪个处理程序对应于URI,如何解释它取决于你。为请求方法编写快捷方式快捷方式可用于GET、POST、PUT、PATCH、DELETE和HEAD请求方法。$r->get('/get-route','get_handler');$r->post('/post-route','post_handler');//相当于$r->addRoute('GET','/get-route','get_handler');$r->addRoute('POST','/post-route','post_handler');路由组可以在一个组内定义路由,同一组内的路由具有相同的前缀。$r->addGroup('/admin',function(RouteCollector$r){$r->addRoute('GET','/do-something','handler');$r->addRoute('GET','/do-another-thing','handler');$r->addRoute('GET','/do-something-else','handler');});//等同于$r->addRoute('GET','/admin/do-something','handler');$r->addRoute('GET','/admin/do-another-thing','handler');$r->addRoute('GET','/admin/do-something-else','handler');可以定义多级嵌套组结构。可以无缝缓存使用simpleDispatcher定义的路由的回调。通过使用cachedDispatcher而不是simpleDispatcher,可以缓存生成的路由数据并根据缓存的信息构建调度。addRoute('GET','/user/{name}/{id:[0-9]+}','handler0');$r->addRoute('GET','/user/{id:[0-9]+}','handler1');$r->addRoute('GET','/user/{name}','handler2');},['cacheFile'=>__DIR__.'/route.cache',/*需要的缓存文件路径,必须设置*/'cacheDisabled'=>IS_DEBUG_ENABLED,/*可选,启用默认是否缓存,可选参数,默认开启*/]);该函数的第二个参数是一个选项数组,可以用来指定缓存文件路径等。调度URI通过调用dispatch()调度URI。此方法接受HTTP方法和URI作为参数。获取这两条信息是你自己的工作,这个库没有绑定到PHPwebSAPIs。dispatch()返回一个数组,第一个元素是一个状态码,状态码是Dispatcher::NOT_FOUND、Dispatcher::METHOD_NOT_ALLOWED、Dispatcher::FOUND中的一个。对于Dispatcher::METHOD_NOT_ALLOWED状态,第二个数组元素包含提供的URI允许的HTTP方法列表。[FastRoute\Dispatcher::METHOD_NOT_ALLOWED,['GET','POST']]对于Dispatcher::FOUND状态,第二个数组元素是$handler,第三个数组元素是一个包含所有占位符的数组/*针对GET的路由/user/nikic/42*/[FastRoute\Dispatcher::FOUND,'handler0',['name'=>'nikic','id'=>'42']]重写了路由解析器和调度器这个库使用三个组件、路由解析器、数据生成器和调度器。这三个组件实现了以下接口publicfunctiongetData();}interfaceDispatcher{constNOT_FOUND=0,FOUND=1,METHOD_NOT_ALLOWED=2;publicfunctiondispatch($httpMethod,$uri);}路由解析器获取路由模式字符串并将其转换为路由信息数组,其中每个路由信息是其部分数组。/*路由/user/{id:\d+}[/{name}]转换为以下数组:*/[['/user/',['id','\d+'],],['/user/',['id','\d+'],'/',['name','[^/]+'],],]然后可以将此数组传递给addRoute()方法,添加完所有路由后,调用构建器的getData(),它将返回调度器所需的所有路由数据。调度程序通过构造函数接受路由数据并提供dispatch()方法。路由解析器可以单独覆盖,但是数据生成器和调度器应该始终一起修改,因为前者的输出与后者的输入紧密耦合。当使用simpleDispatcher/cachedDispatcher时,你可以通过传入额外的参数来覆盖它FastRoute\\RouteParser\\Std','dataGenerator'=>'FastRoute\\DataGenerator\\GroupCountBased','dispatcher'=>'FastRoute\\Dispatcher\\GroupCountBased',]);上面给出了默认的Setting,将GroupCountBased换成GroupPosBased,就可以使用完全不同的调度策略。关于HEAD请求HTTP规范要求服务器同时支持GET和HEAD方法。所有通用服务器都必须支持GET和HEAD方法,以避免强制用户手动获取每个资源。注册一个HEAD路由,它将响应具有匹配GET路由的请求。PHPwebSAPI透明地从HEAD响应中删除实体主体,因此这种行为对绝大多数用户没有影响。但是,在WebSAPI环境之外使用FastRoute,不得发送为响应HEAD请求而生成的实体主体,如果您是非SAPI用户,这是您的责任;在这种情况下,FastRoute无权限制您破坏HTTP。最后,请注意,应用程序始终可以为给定资源指定自己的HEAD方法路由,以完全绕过此行为。总结文档还是很通俗易懂的,下次再看源码。原创文章,欢迎转载。转载请注明出处,谢谢。原文链接地址:http://dryyun.com/2018/04/20/...作者:dryyun发表日期:2018-04-2110:14:21