文档/事件

事件

HLEB2 框架中有几个预定义的常规事件,每个事件都分配给特定的动作类型。
所有事件类都位于 /app/Bootstrap/Events/ 文件夹中,可以进行修改。从技术上讲,它们替代了配置,消除了项目中不必要的“魔法”。

由于这些类与全局事件相关联,建议将依赖于私有实现的代码分离到单独的类中。

未优化的事件中的代码可能会导致项目整体性能下降。


#ControllerEvent

此类的 before() 方法在框架的每次控制器调用之前执行。它允许您确定涉及哪个类和方法,并在需要时更改作为命名数组提供的参数,并将它们返回到被调用的控制器方法。
例如,如果使用第三方库验证传入请求,可以通过 ControllerEvent 事件实现此检查。

如果存在,after() 方法允许重定义控制器的响应,并在控制器之后立即执行。该方法通过引用在 'result' 参数中接收此结果,允许您更改特定类和方法的返回数据。
全局上,这可能涉及将返回的数组从默认的 JSON 更改为另一个格式,如 XML

以下示例演示了在调用特定类和控制器方法之前附加额外操作:

<?php

declare(strict_types=1);

namespace 
App\Bootstrap\Events;

use 
Hleb\Base\Event;

final class 
ControllerEvent extends Event
{
    public function 
before(string $classstring $method, array $arguments): array|false
    
{
        switch([
$class$method]) {
            case [
ExampleController::class, 'index']:
                return (new 
ExampleControllerEvent())->beforeIndex($arguments);
                
// ... //
            
default:
        }
        return 
$arguments;
    }

    public function 
after(string $classstring $methodmixed &$result): void
    
{
        
// ... //
    
}
}

#MiddlewareEvent

这个中间件类的 before() 方法在框架的每次 middleware 调用之前执行。该方法的参数允许您确定涉及哪个类和方法,以及此 middleware 是否在主要操作之后执行。
如有必要,可以更改目标 middleware 方法的参数,进行更改,并从当前方法返回。如果是这种情况,需要定义条件以便在结果输出后终止脚本执行,可以通过从 after() 方法返回 false 来实现。

中间件的执行顺序可以通过路由改变,这在为其分配事件时必须考虑到,如有必要,可将依赖于执行顺序的事件元素替换为相应的独立中间件。


#ModuleEvent

由于模块是独立存在的,每个模块的控制器都有自己的事件。
ModuleEvent 类的 before() 方法在框架中任何模块的每次控制器调用之前执行。
ControllerEvent 不同,增加了一个额外的参数 $module 来确定模块名称。
与控制器事件相似,此事件也可以有一个 after() 方法。


#PageEvent

这是另一个类似于 ControllerEvent 的事件,绑定到特殊“页面控制器”的调用。
此类页面用于框架的注册库中的管理面板以及此文档网站上。


#TaskEvent

在每次框架命令启动之前执行,排除了那些默认内置的命令。 还可以确定被调用的类和调用的来源(来自代码或来自控制台)。 TaskEvent 接收并返回最终方法的参数的最终数据,因此可以在此处连接第三方库。 例如,这可以是来自 Symfony 的标准控制台处理程序。

这个事件的 after() 方法的不同之处在于它可以访问任务中设置为 setResult() 的数据。 这些数据通过引用传递给 'result' 参数,并且可以被修改。
如有必要,可以通过使用 statusCode() 方法以相同的方式更改返回的响应状态。

演示示例,展示了一种组织响应到不同任务的执行(使用一个通用接口)的方法:

<?php

namespace App\Bootstrap\Events;

use 
Hleb\Base\Event;

final class 
TaskEvent extends Event
{
    private ?
TaskEventInterface $action null;

    public function 
before(string $classstring $method, array $args): array
    {
        switch (
$class) {
            case 
FirstTask::class:
                
$this->action = new FirstTaskEvent($method);
                break;
            case 
SecondTask::class:
                
$this->action = new SecondTaskEvent($method);
                break;
            
// ... //
            
default:
        }
        return 
$this->action $this->action->getBeforeAction($args) :  $args;
    }

    public function 
after(string $classstring $methodmixed &$result): void
    
{
        
$this->action and $result $this->action->updateAfterAction($result);
    }

    public function 
statusCode(string $classstring $methodint $code): int
    
{
        return 
$this->action $this->action->getCode($code) : $code;
    }
}

此原则不仅可以应用于任务事件,也可以应用于其他事件。

为事件选择 switch 操作符是因为它能够将一个结果与多个 case 块匹配。


#扩展条件

可以根据其他条件分配关联的动作,例如,通过 namespace 中的一般组:

if (str_starts_with($class'App\\Controllers\\Api\\')) {
    
// ... //
}

此外,事件类继承自 Hleb\Base\Container,这使得它们可以使用容器中的服务。 在事件类的构造函数中也可以通过 Dependency Injection 获取这些服务。
使用的可能性没有限制,当然要保持代码的可读性和优化。 下面是如何为特定的类和方法设置基于 HTTP 请求方法的条件:

if ([$class$method] === [MainController::class, 'index'] && $this->request()->isMethod('GET')) {
    
// ... //
}
控制台命令 介绍

页面翻译:chatgpt 4-o
返回顶部