exedron / routeller
基于注解的Exedra路由控制器
Requires
- minime/annotations: ~3.0
- rosengate/exedra: dev-master
This package is not auto-updated.
Last update: 2024-09-15 01:32:31 UTC
README
- Deprecated : This package has already been merged with https://github.com/rosengate/exedra
\Exedron\Routeller
Exedra的一个基于注解和反射的瘦路由控制器。
简单来说,这是在steroid中用于路由的组件。
简介
为深层嵌套的路由编写大量的\Closure会使代码变得混乱,并且随着代码量的增加,IDE的支持性也不够友好。这个包就是为了解决这一问题,并为你的路由组提供了一个优雅的路由控制器。
控制器是瘦的、扁平的,不能构建,但对路由设计非常了解。
注解设计相当简单,只是@property-value映射。没有太多内容!
要求
这个包只为Exedra工作。它不能独立使用,因为……当然,它是Exedra路由组件的一部分。
安装和用法
安装
通过composer安装
composer require exedron\routeller dev-master
通过服务提供商添加
设置服务提供商
// your application instance $app->provider->add(\Exedron\Routeller\Provider::class);
通过路由工厂添加
或者,你也可以手动添加处理程序,并设置其他一些内容。
$app->routingFactory->addGroupHandler(new \Exedron\Routeller\Handler($app)); $app->map->addExecuteHandler('routeller_execute', ExecuteHandler::class);
启用缓存
启用基于文件的缓存
$options = array( 'auto_reload' => true ); $cache = new \Exedron\Routeller\Cache\FileCache(__DIR__ .'/routing_caches') $app->provider->add(new \Exedron\Routeller\Provider($cache, $options));
当控制器发生变化时,auto_reload选项允许它重新加载缓存。
用法
在你的路由上,使用group()方法添加控制器。
$app->map['web']->group(\App\Controller\WebController::class);
控制器必须是\Exedron\Routeller\Controller\Controller的类型。
<?php namespace App\Controller; use Exedron\Routeller\Controller\Controller; class WebController extends Controller { }
添加可执行路由
使用路由属性注解方法。方法名必须以前缀execute开头。
<?php namespace App\Controller; use Exedra\Runtime\Context; class WebController extends \Exedron\Routeller\Controller\Controller { /** * @path / */ public function executeIndex(Context $context) { return 'This is index page'; } /** * @name about-us * @path /about-us * @method GET|POST */ public function executeAboutUs(Context $context) { return 'This is about page'; } }
上面的操作与下面的操作类似
use Exedra\Routing\Group; use Exedra\Runtime\Context; $app->map['web']->group(function(Group $group) { $group['index']->any('/')->execute(function(Context $context) { return 'This is index page'; }); $group['about-us']->any('/about-us')->execute(function(Context $context) { return 'This is about page'; }); });
添加普通路由
你可能想要以面向对象的方式自定义路由,前缀为route。
/** * @path /faq */ public function routeFaq(\Exedra\Routing\Route $route) { $route->execute(function() { }); }
中间件
通过在方法名前缀为middleware为当前组的路由添加中间件。此方法不需要注解。
public function middlewareAuth(Context $context) { if(!$context->session->has('user_id')) return $context->redirect->route('@web.login'); return $context->next($context); }
尽管中间件名称是可选的,但你仍然可以设置它。
/** * @name csrf */ public function middlewareCsrf() { return $context->next($context); }
子路由/嵌套路由
添加子组路由。方法名必须以前缀group开头。
该方法必须返回路由组模式。
/** * @path /products */ public function groupProducts() { return \App\Controller\ProductController::class; }
立即子路由
与group前缀类似,但这个方法会立即解析其组。
/** * @path /:product-id */ public function subProduct(Group $group) { $group['get']->get('/')->execute(function() { // do your things }); $group['update']->post('/')->execute(function() { // do your things }); }
普通路由
你也可以通过在方法名前缀为setup来执行通常的路由。此方法不需要注解。
public function setup(Group $group) { $group->get('/')->execute(function() { }); } public function setupCustom(Group $group) { // do another thing }
此方法还接收Exedra\Application作为第二个参数。
/** * @path /comments */ public function setup(Group $group, \Exedra\Application $app) { $group->get('/')->execute(function() { }); }
RESTful动词
此包还支持简单的RESTful映射。
GET、POST、PUT、PATCH、DELETE动词
根据需要将每个方法前缀为HTTP动词。
/** * Get all products * @path / */ public function getProducts(Context $context) { }
/** * Create a new product * @path / */ pubic function postProducts(Context $context) { }
/** * GET the product * @path /[:id] */ pubic function getProduct(Context $context) { }
/** * DELETE the product * @path /[:id] */ pubic function getProduct(Context $context) { }
仅动词方法名
你还可以有一个只有动词的路由。
public function get(Context $context) { } public function post(Context $context) { }
当然,这只是一个示例。在Exedra中进行资源设计最佳的方式是通过子路由。
依赖注入
使用已知服务(s)注入
use Exedra\Url\UrlGenerator; /** * @inject context.url * @path / */ public function get(UrlGenerator $url) { echo $url->current(); }
多个服务
use Exedra\Runtime\Context; use Exedra\Application; use Exedra\Routing\Group; /** * @inject context, url, self.response, app, app.map * @path / */ public function post(Context $context, $url, $response, Application $app, Group $map) { }
注意
self和context是同一类型,是\Exedra\Runtime\Context,当前运行时的上下文。- 以
app.前缀的服务将在Exedra\Application容器中查找 - 没有前缀,如
context.、self.或app.,解析器将只查找注册了 Context 对象的服务。
其他路由属性
标记和 AJAX
/** * @tag users * @ajax true * @middleware \App\Middleware\Auth */ pubic function executeUsers() { }
属性(以及示例中间件)
public function middlewareAuth(\Exedra\Runtime\Context $context) { if($context->attr('need_auth', false) && !$context->session->has('user_id')) throw new NotLoggedInException; return $context->next($context); } /** * @attr.need_auth true * @path /admin * @method any */ public function groupAdmin() { return Admin::class; }
所有可能的属性
/** * @name admin_default * @method GET|POST * @path /admin/:controller/:action * @middleware \App\Middleware\Auth * @middleware \App\Middleware\Csrf * @middleware \App\Middleware\Limiter * @tag admin_default * @attr.session_timeout 36000 * @config.request_limit 15 */ public function executeAdminDefault($context) { // nah, just a sample. $controller = $context->param('controller'); $action = $context->param('action'); return (new $controller)->{$action}($context); }
异常
非路由属性标签,如 return、param 和 throws 标签将不会被解析。
控制台命令
此包还提供了一个类似的命令在原始路由列表中,只是它增加了更多关于结果细节。
$app = new \Exedra\Application(__DIR__); //... do some routing $console = new \Symfony\Component\Console\Application(); $console->add(new \Exedron\Routeller\Console\Commands\RouteListCommand($app, $app->map)); $console->run();
注意
路由名称
对于某些类型的用法,如 executable 和 grouped 类型的路由,如果未注解 @name 属性,则路由名称将从剩余的小写方法名称中获取。
RESTful 控制器的路由名称
它结合了动词和方法名称。例如,
public function postProducts() { } public function get() { }
上述路由将具有类似 .post-products 的方法名称。(@web.products.post-products)
对于只有动词的方法名称,它将只是动词作为名称。其绝对名称可能看起来像: @web.products.get
排序
路由顺序是从上到下读取的。因此,你的路由编写方式很重要。