mezon / router
小巧快速的路由框架
Requires
- php: >=7.4.0
Requires (Dev)
- infection/infection: ^0.21.5
- mezon/functional: ^1.0
- phpunit/phpunit: ^8.5
- vimeo/psalm: ^4.2
- dev-master
- 1.5.1
- 1.5.0
- 1.4.0
- 1.3.6
- 1.3.5
- 1.3.4
- 1.3.3
- 1.3.2
- 1.3.1
- 1.3.0.x-dev
- 1.3.0
- 1.2.14.x-dev
- 1.2.14
- 1.2.13
- 1.2.12
- 1.2.11
- 1.2.10
- 1.2.9
- 1.2.8
- 1.2.7
- 1.2.6
- 1.2.5
- 1.2.4
- 1.2.3
- 1.2.2
- 1.2.1
- 1.2.0
- 1.1.3
- 1.1.2
- 1.1.1
- 1.1.0
- 1.0.21
- 1.0.20
- 1.0.19
- 1.0.18
- 1.0.17
- 1.0.16
- 1.0.15
- 1.0.14
- 1.0.13
- 1.0.12
- 1.0.11
- 1.0.10
- 1.0.9
- 1.0.8
- 1.0.7
- 1.0.6
- 1.0.5
- 1.0.4
- 1.0.3
- 1.0.2
- 1.0.1
- 1.0.0
This package is auto-updated.
Last update: 2024-09-13 16:41:52 UTC
README
简介
Mezon Framework 提供简单路由类,满足您的需求。它已被用于 Web应用、服务、CRUD服务。
贡献者
Mezon之所以变得更好,是因为有贡献者。也要感谢他们。
再次感谢大家的贡献。
如果您也想支持我们的项目,请使用此链接。
常见问题解答
有问题请使用此服务提问。
安装
只需在控制台打印
composer require mezon/router
这就是全部。
使用理由
mezon/router 是
- 比 klein/klein 路由快 25 倍
- 比 Symfony 路由快 7 到 15 倍
- 比 Laravel 路由快 30 到 50 倍
- 比 nikic/fast-route 快 1.5 倍
更多基准测试信息请见这里。
了解更多
更多信息请见此处
什么是“第一种情况”和“第二种情况”?
-
第一种情况 - http服务器接受请求,启动php脚本,处理该请求,然后将所有脚本数据从内存中上传。所有后续请求都以此方式处理。在这种情况下,尽快启动脚本至关重要,我们无法花时间进行长时间的预编译和准备,因为所有这些都将随着脚本完成工作而丢失。
-
第二种情况 - php脚本启动,初始化所有内部组件(其中之一是路由器)然后开始处理请求。这种情况可以通过例如react-php来组织。与之前的情况不同,因为我们可以花合理的时间预先编译路由以加快速度。
在此表中,您可以查看每秒的请求数量。数字越大越好。
如果您能按下“STAR”按钮,我将非常高兴
简单路由
路由器允许您将URL映射到您的PHP代码上,并在需要时调用。
路由器支持简单的路由,如上面的示例 - example.com/contacts/
每个Application对象都会隐式创建其action[action-name]
方法的路由,其中action-name
将作为路由存储。这里有一个小(如往常一样)的例子
class MySite { /** * Main page */ public function actionIndex() { return 'This is the main page of our simple site'; } /** * FAQ page */ public function actionFaq() { return 'This is the "FAQ" page'; } /** * Contacts page */ public function actionContacts() { return 'This is the "Contacts" page'; } /** * Some custom action handler */ public function someOtherPage() { return 'Some other page of our site'; } /** * Some static method */ public static function someStaticMethod() { return 'Result of static method'; } }
这段代码
$router = new \Mezon\Router\Router(); $router->fetchActions($mySite = new MySite());
将创建路由器对象,并加载其动作信息以及创建路由。严格来说,它将创建两个路由,因为MySite类只有两个以action[Suffix]
开头的方法。方法someOtherPage
不会自动转换为路由。默认情况下,此方法将创建处理POST和GET请求方法的路由。
然后只需通过URL调用回调函数即可
$router->callRoute('/index/');
有一种方法可以指定每个动作的请求方法
$router->fetchActions($mySite = new MySite(), [ 'Index' => 'GET', 'Contacts' => 'POST', 'Faq' => ['GET', 'POST'], ]);
您可以手动指定应用程序中每个URL的回调函数
$router->addRoute('/some-any-other-route/', [$mySite, 'someOtherPage']);
您还可以使用静态方法
$router->addRoute('/static-route/', ['MySite', 'someStaticMethod']); // or in this way $router->addRoute('/static-route/', 'MySite::someStaticMethod');
我们只需要显式地创建它。
我们还可以使用简单函数来创建路由
function sitemap() { return 'Some fake sitemap'; } $router->addRoute('/sitemap/', 'sitemap');
您可以在不启动它的情况下找到回调
$router->addRoute('/static-route/', 'MySite::someStaticMethod'); $callback = $router->getCallback('/static-route/'); var_dump($callback());
支持请求方法
Mezon Router支持
- GET
- POST
- PUT
- DELETE
- OPTION
- PATCH
要获取这些方法的列表,您可以使用getListOfSupportedRequestMethods方法
$router = new \Mezon\Router\Router(); var_dump($router->getListOfSupportedRequestMethods());
一个处理器处理所有路由
您可以为所有路由指定一个处理器,如下所示
$router->addRoute('/*/', function(){});
请注意,如果找到*
处理器,路由搜索将停止。例如
$router->addRoute('/*/', function(){}); $router->addRoute('/index/', function(){});
在这个例子中,路由/index/永远不会被访问。所有请求都将传递到*
处理器。但是在本例中
$router->addRoute('/contacts/', function(){}); $router->addRoute('/*/', function(){}); $router->addRoute('/index/', function(){});
路由/contacts/将由其处理器处理,而所有其他路由(包括/index/)将由*
处理器处理。
路由变量
现在是一些更复杂的路由
$router->addRoute('/catalogue/[i:cat_id]/', function($route, $variables){}); $router->addRoute('/catalogue/[a:cat_name]/', function($route, $variables){});
这里
- i - 任何整数数字
- a - 任何[a-z0-9A-Z_/-.@]+字符串
- il - 以逗号分隔的整数ID列表
- s - 任何字符串
参数名必须由以下字符组成:[a-zA-Z0-9_-]
所有这些变量都作为第二个函数参数传递,如下例所示 - $variables。所有变量都以关联数组的形式传递。
请求类型和REST API的第一步
您可以将处理器绑定到不同的请求类型,如下所示
$router->addRoute('/contacts/', function(){}, 'POST'); // this handler will be called for POST requests $router->addRoute('/contacts/', function(){}, 'GET'); // this handler will be called for GET requests $router->addRoute('/contacts/', function(){}, 'PUT'); // this handler will be called for PUT requests $router->addRoute('/contacts/', function(){}, 'DELETE'); // this handler will be called for DELETE requests $router->addRoute('/contacts/', function(){}, 'OPTION'); // this handler will be called for OPTION requests $router->addRoute('/contacts/', function(){}, 'PATCH'); // this handler will be called for PATCH requests
反向路由
您可以通过路由的名称反向路由和编译URL。例如
$router = new \Mezon\Router\Router(); $router->addRoute('/some-route/[i:id]', function(){}, 'GET', 'name of the route'); // will output /some-route/123 var_dump($router->reverse('name of the route', ['id' => 123]));
路由缓存
从版本1.1.0开始,您可以将路由缓存到磁盘并从中读取。
要将其导出到磁盘,请使用
$router->dumpOnDisk('./cache/cache.php');
然后您可以加载路由
$router->loadFromDisk('./cache/cache.php');
但是,这些方法有一些限制 - 由于明显的原因,它们不能导出和加载闭包。
您还可以在不导出的情况下预热缓存
$router->warmCache();
中间件和参数修改
您可以在路由处理器执行之前添加的中间件类型。此中间件可以将常见的参数$ route和$ parameters转换为不同的内容。
- 多个全局中间件,将按附加顺序调用。
- 多个路由特定中间件,将按附加顺序调用。
中间件的执行顺序
- 全局中间件
$router->addRoute('*', ...)
。 - 在调用路由回调
$router->addRoute('/example', ...)
之前,将执行所有匹配的路由。
让我们看看一个简单的例子
$router = new Router(); $router->addRoute('/user/[i:id]', function(string $route, array $parameters){ $userModel = new UserModel(); $userObject = $userModel->getUserById($parameters['id']); // use $userObject for any purpose you need });
现在让我们看看一个包含所有可能性的例子。
$router = new Router(); // First step. We have an API that talks JSON, convert the body $router->registerMiddleware('*', function (string $route, array $parameters){ $request = Request::createFromGlobals(); $parameters['_request'] = $request; $parameters['_body'] = json_decode($request->getContent(), true); return $parameters; }); // Second step. Ensure that we are logged in when we are in the private area $router->registerMiddleware('*', function (string $route, array $parameters){ // Is not a private area if (mb_strpos($route, '/user') !== 0 || empty($parameters['user_id'])) { return $parameters; } $token = $parameters['_request']->headers->get('oauth_token'); $auth = new SomeAuth(); $auth->validateTokenOrFail( $token, $parameters['user_id'] ); // We don't need to return nothing }); // Last step. Now we will modify the parameters so the handler can work with them $router->registerMiddleware('/user/[i:user_id]', function(string $route, array $parameters){ $userModel = new UserModel(); return $userModel->getUserById( $parameters['user_id'] ); }); // Final destination. We have ended the middlewares, now we can work with the processed data $router->addRoute('/user/[i:user_id]', function (UserObject $userObject){ // Do everything });
PSR-7路由处理
最初,Mezon Router并非为PSR-7兼容而设计。但最新功能之一使其成为可能。您可以使用中间件来实现此目的。例如
$router = new Router(); $router->addRoute('/user/[i:id]', function(\Nyholm\Psr7\Request $request){ // work here with the request in PSR-7 way $psr17Factory = new \Nyholm\Psr7\Factory\Psr17Factory(); $responseBody = $psr17Factory->createStream('Hello world'); $response = $psr17Factory->createResponse(200)->withBody($responseBody); (new \Zend\HttpHandlerRunner\Emitter\SapiEmitter())->emit($response); }); $router->registerMiddleware('/user/[i:id]', function(string $route, array $parameters){ $psr17Factory = new \Nyholm\Psr7\Factory\Psr17Factory(); $creator = new \Nyholm\Psr7Server\ServerRequestCreator( $psr17Factory, // ServerRequestFactory $psr17Factory, // UriFactory $psr17Factory, // UploadedFileFactory $psr17Factory // StreamFactory ); return $creator->fromGlobals(); });
最好的事情是 - 如果您在项目中不使用PSR-7,那么您就不会“付费”。
自定义类型
您可以为URL解析器定义自己的类型。让我们尝试创建date
类型。
首先,我们应该创建一个简单的类
class DateRouterType { /** * Method returns regexp for searching this entity in the URL * * @return string regexp for searching */ public static function searchRegExp(): string { return '(\[date:'.BaseType::PARAMETER_NAME_REGEXP.'\])'; } }
这里BaseType::PARAMETER_NAME_REGEXP是一个全局设置,它告诉路由器参数名必须由以下字符组成
- a-z和A-Z字母
- 0-9
- 以及_和-符号
现在我们需要定义一个额外的类方法,该方法将在出现日期时解析日期
public static function parserRegExp(): string { // pretty simple regexp return '([0-9]{4}-[0-9]{2}-[0-9]{2})'; }
并在您的配置文件中的某个位置启用此类型
$router->addType('date', DateRouterType::class);
现在您可以这样处理路由
/some-url-part/2020-02-02/ending-part/ /posts-for-2020-02-02/
但是要小心。例如,您将定义这样的路由
$router->addRoute('/posts-for-[date:posts-date]/', function(UserObject $userObject){ // some activities here }); $router->addRoute('/[s:some-url]/', function(UserObject $userObject){ // some activities here });
然后第一个处理器/posts-for-[date:posts-date]/
将为路由/posts-for-2020-02-02/
调用。