thewunder/croute

基于约定的PHP路由

2.0.1 2022-06-22 21:36 UTC

This package is auto-updated.

Last update: 2024-09-22 16:41:18 UTC


README

Latest Version on Packagist Software License

基于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

它支持嵌套命名空间,因此

属性

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个事件

  1. router.request
  2. router.controller_loaded
  3. router.controller_loaded.{ControllerName}
  4. router.before_action
  5. router.before_action.{ControllerName}
  6. router.before_action.{ControllerName}.{actionName}
  7. router.after_action
  8. router.after_action.{ControllerName}
  9. router.after_action.{ControllerName}.{actionName}
  10. router.before_response_sent
  11. router.response_sent
  12. router.response_sent.{ControllerName}
  13. 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