thewunder / croute
基于约定的PHP路由
2.0.1
2022-06-22 21:36 UTC
Requires
- php: >=8.0
- psr/event-dispatcher: ^1.0
- symfony/http-foundation: ^5.0||^6.0
- symfony/routing: ^5.0||^6.0
Requires (Dev)
- mikey179/vfsstream: ~1.0
- php-coveralls/php-coveralls: ^2.2
- phpunit/phpunit: ^9.0
- symfony/event-dispatcher: ^6.0
README
基于Symfony组件的PHP的约定路由。
Croute之所以优秀,是因为
- 你不需要维护路由表
- 促进代码组织的统一性
- 允许通过属性和事件进行自定义
通过Composer安装
通过命令行
composer.phar require thewunder/croute ^2.0
或者在composer.json的require部分添加以下内容
"thewunder/croute": "^2.0"
基础
你的index.php应该看起来像这样
$router = Router::create($eventDispatcher, ['Your\\Controller\\Namespace'], $container, [$dependency1, $dependency2]); $router->route($request);
你的控制器应该看起来像这样
namespace Your\Controller\Namespace class IndexController extends Croute\Controller { public function __construct($dependency1, $dependency2) { //... } /** * Will be available at http://yourdomain/ * and require the "required" (body or querystring) request parameter */ public function indexAction($required, $optional = null) { echo 'Crouter Controller'; //you can echo or return a symfony Response } /** * Available at http://yourdomain/test */ public function testAction() { return new Response('Test Action'); } }
控制器的名称决定了它出现的URL
- http://yourdomain/my/ -> Your\Controller\Namespace\MyController::indexAction()
- http://yourdomain/my/action -> Your\Controller\Namespace\MyController::actionAction()
它支持嵌套命名空间,因此
- http://yourdomain/level1/level2/save -> Your\Controller\Namespace\Level1\Level2\IndexController::saveAction()
属性
Croute可选支持控制器和动作属性。默认包含两个属性,HttpMethod和Secure。
HttpMethod
限制允许的HTTP方法。如果方法不匹配,则返回400响应。
#[HttpMethod('POST')] public function saveAction()
Secure
需要安全连接。如果连接不是https,则发送301重定向到同一URL,使用https协议。
#[Secure] class IndexController extends Controller {
自定义属性
要创建自定义属性,在你的属性上实现RoutingAttribute接口,并实现一个AttributeHandler。
#[\Attribute(\Attribute::TARGET_CLASS|\Attribute::TARGET_METHOD)] class MyAttribute implements RoutingAttribute { public function __construct(public string $option) {} }
class MyAttributeHandler extends BasicAttributeHandler { public function getAttributeClass(): string { return MyAttribute::class; } public function handleRequest(MyAttribute|RoutingAttribute $attribute, Request $request): ?Response { // Return a response will immediately return that response, bypassing the normal controller action if ($attribute->option == 'teapot') { return new Response("I'm a teapot", Response::HTTP_I_AM_A_TEAPOT); } return null; } }
将属性处理程序添加到路由器中,然后你的自定义属性就可以使用了。
$router->addAttributeHandler(new MyAttributeHandler());
事件
在路由过程的每个步骤都会触发Symfony事件。在成功的请求中,总共会触发12个事件
- router.request
- router.controller_loaded
- router.controller_loaded.{ControllerName}
- router.before_action
- router.before_action.{ControllerName}
- router.before_action.{ControllerName}.{actionName}
- router.after_action
- router.after_action.{ControllerName}
- router.after_action.{ControllerName}.{actionName}
- router.before_response_sent
- router.response_sent
- router.response_sent.{ControllerName}
- router.response_sent.{ControllerName}.{actionName}
{ControllerName}将不带'Controller',{actionName}将不带'Action',即IndexController::indexAction -> router.before_action.Index.index。
在响应发送之前,你可以在事件监听器中设置响应以绕过动作并发送。
public function myListener(ControllerLoadedEvent $event) { $event->setResponse(new Response('PermissionDenied', 403)); }
错误处理
正确的错误处理不是我可以为你做的。你需要自己确定如何进行日志记录,如何和何时渲染一个漂亮的错误页面。要处理错误,实现EventHandlerInterface并在路由器上设置你的错误处理程序。当发生常见的路由事件(例如404错误)以及路由过程中有异常时,你的类将被调用。
贡献
有关详细信息,请参阅CONTRIBUTING。