• Hyperf 事件机制


    前言

    事件模式必须基于 PSR-14 去实现。
    Hyperf 的事件管理器默认由 hyperf/event 实现,该组件亦可用于其它框架或应用,只需通过 Composer 将该组件引入即可。

    composer require hyperf/event

    概念

    事件模式是一种经过了充分测试的可靠机制,是一种非常适用于解耦的机制,分别存在以下 3 种角色:

    • 事件(Event) 是传递于应用代码与 监听器(Listener) 之间的通讯对象
    • 监听器(Listener) 是用于监听 事件(Event) 的发生的监听对象
    • 事件调度器(EventDispatcher) 是用于触发 事件(Event) 和管理 监听器(Listener) 与 事件(Event) 之间的关系的管理者对象

    用通俗易懂的例子来说明就是,假设我们存在一个 UserService::register() 方法用于注册一个账号,在账号注册成功后我们可以通过事件调度器触发 UserRegistered 事件,由监听器监听该事件的发生,在触发时进行某些操作,比如发送用户注册成功短信,在业务发展的同时我们可能会希望在用户注册成功之后做更多的事情,比如发送用户注册成功的邮件等待,此时我们就可以通过再增加一个监听器监听 UserRegistered 事件即可,无需在 UserService::register() 方法内部增加与之无关的代码。

    使用场景 

    1、用户注册之前检查用户是否有权注册

    2、用户注册成功之后发送短信、发送邮件、记录日志

    这里需要定义两个事件:

    1、用户注册权限检测事件BeforeUserRegister

    2、用户注册事件UserRegister

    还需要定义四个监听器

    1、用户权限验证监听 ValidateRegisterListener.php

    2、邮件发送 SendEmailListener.php

    3、短信发送 SendSmsListener.php

    4、记录日志 LoginEventListener.php

    调用方法 

    EventController->test()

     定义事件

    <?php
    
    
    namespace AppEvent;
    /**
     * @property int $userId
     */
    class UserRegister
    {
        public $userId;
        public function __construct($userId)
        {
            $this->userId = $userId;
        }
    }
    <?php
    namespace AppEvent;
    use HyperfUtilsContext;
    
    /**
     * @property bool $shouldRegister
     */
    class BeforeUserRegister
    {
    
    //    protected $shouldRegister;
    
        public function __get($name)
        {
            // TODO: Implement __get() method.
            return Context::get(__CLASS__.":".$name);
        }
    
        public function __set($name, $value)
        {
            // TODO: Implement __set() method.
            return Context::set(__CLASS__.":".$name,$value);
        }
    }

    定义监听器

    php bin/hyperf.php gen:listener SendSmsListener
    php bin/hyperf.php gen:listener SendEmailListener
    php bin/hyperf.php gen:listener ValidateRegisterListener
    php bin/hyperf.php gen:listener LoginEventListener
    <?php
    
    declare(strict_types=1);
    
    namespace AppListener;
    
    use AppEventBeforeUserRegister;
    use AppEventUserRegister;
    use HyperfEventAnnotationListener;
    use PsrContainerContainerInterface;
    use HyperfEventContractListenerInterface;
    
    /**
     * @Listener
     */
    class LoginEventListener implements ListenerInterface
    {
        /**
         * @var ContainerInterface
         */
        private $container;
    
        public function __construct(ContainerInterface $container)
        {
            $this->container = $container;
        }
    
        public function listen(): array
        {
            return [
                BeforeUserRegister::class,
                UserRegister::class,
            ];
        }
    
        public function process(object $event)
        {
            if($event instanceof BeforeUserRegister){
                echo get_class($event).$event->shouldRegister.PHP_EOL;
            }else if ($event instanceof UserRegister){
                echo get_class($event).$event->userId.PHP_EOL;
            }
        }
    }
    <?php
    
    declare(strict_types=1);
    
    namespace AppListener;
    
    use AppEventUserRegister;
    use HyperfEventAnnotationListener;
    use PsrContainerContainerInterface;
    use HyperfEventContractListenerInterface;
    
    /**
     * @Listener(priority=9)
     */
    class SendEmailListener implements ListenerInterface
    {
        /**
         * @var ContainerInterface
         */
        private $container;
    
        public function __construct(ContainerInterface $container)
        {
            $this->container = $container;
        }
    
        public function listen(): array
        {
            return [
                UserRegister::class
            ];
        }
    
        /**
         *
         * @param UserRegister $event
         * @author liubo 2020-06-12 15:12
         */
        public function process(object $event)
        {
            echo "发送Email给".$event->userId.PHP_EOL;
        }
    }
    <?php
    
    declare(strict_types=1);
    
    namespace AppListener;
    
    use AppEventUserRegister;
    use HyperfEventAnnotationListener;
    use PsrContainerContainerInterface;
    use HyperfEventContractListenerInterface;
    
    /**
     * @Listener(priority=10)
     */
    class SendSmsListener implements ListenerInterface
    {
        /**
         * @var ContainerInterface
         */
        private $container;
    
        public function __construct(ContainerInterface $container)
        {
            $this->container = $container;
        }
    
        public function listen(): array
        {
            return [
                UserRegister::class
            ];
        }
    
        /**
         *
         * @param UserRegister $event
         * @author liubo 2020-06-12 15:12
         */
        public function process(object $event)
        {
            echo "发送短信给".$event->userId.PHP_EOL;
        }
    }
    <?php
    
    declare(strict_types=1);
    
    namespace AppListener;
    
    use AppEventBeforeUserRegister;
    use HyperfEventAnnotationListener;
    use PsrContainerContainerInterface;
    use HyperfEventContractListenerInterface;
    
    /**
     * @Listener
     */
    class ValidateRegisterListener implements ListenerInterface
    {
        /**
         * @var ContainerInterface
         */
        private $container;
    
        public function __construct(ContainerInterface $container)
        {
            $this->container = $container;
        }
    
        public function listen(): array
        {
            return [
                BeforeUserRegister::class
            ];
        }
    
        /**
         *
         * //为了调用方便此处先这样写
         * @param BeforeUserRegister $event
         * @author liubo 2020-06-12 15:27
         */
        public function process(object $event)
        {
            $event->shouldRegister = (bool)rand(0,1);
            if(!$event->shouldRegister){
                echo "很抱歉,您无权注册!".PHP_EOL;
            }else{
                echo "欢迎注册!".PHP_EOL;
            }
        }
    }

    使用示例

    <?php
    namespace AppController;
    use AppServiceUserService;
    use HyperfDiAnnotationInject;
    use HyperfHttpServerAnnotationAutoController;
    
    /**
     * @AutoController()
     */
    class EventController extends AbstractController
    {
        /**
         * @Inject()
         * @var UserService
         */
        private $userService;
    
        public function test(){
            return $this->userService->register();
        }
    
    }
    <?php
    
    
    namespace AppService;
    
    
    use AppEventBeforeUserRegister;
    use AppEventUserRegister;
    use HyperfDiAnnotationInject;
    use PsrEventDispatcherEventDispatcherInterface;
    
    class UserService
    {
        /**
         * @Inject()
         * @var EventDispatcherInterface
         */
        private $eventDispatcher;
    
        public function register()
        {
            //验证是否有注册权限
            $beforeUserRegister=new BeforeUserRegister();
            $this->eventDispatcher->dispatch(new BeforeUserRegister());
            if($beforeUserRegister->shouldRegister){
                //注册用户
                $userId =rand(0,9999);
                //注册成功后
                $this->eventDispatcher->dispatch(new UserRegister($userId));
                return $userId;
            }else{
                return "不可注册!";
            }
        }
    
    }

    运行结果

    欢迎注册!
    AppEventBeforeUserRegister1
    发送短信给6195
    发送Email给6195
    AppEventUserRegister6195
    

      

  • 相关阅读:
    Java面试中常问的Spring方面问题(涵盖七大方向共55道题,含答案)
    Node.js环境搭建
    Node.js的开源博客系统Ghost搭建教程
    探讨一个“无法创建JVM”的问题(已解决)
    Spring Boot快速入门
    Spring Boot开发Web应用
    Spring Boot工程结构推荐
    元类的剖析和单例
    多态的简单剖析、内置方法和异常的解读
    面向对象的解释和属性查找的方式解读
  • 原文地址:https://www.cnblogs.com/bobobobobo/p/13101449.html
Copyright © 2020-2023  润新知