zoukankan      html  css  js  c++  java
  • 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
    

      

  • 相关阅读:
    python 枚举enum
    python lambda 三元表达式
    python修改类属性
    python获取引用对象的个数
    python 返回实例对象个数
    python __del__() 清空对象
    python面向对象:继承
    python面向对象:多态
    Docker容器和K8s添加Health Check
    mkfs.xfs: /dev/vdb appears to contain a partition table (dos)
  • 原文地址:https://www.cnblogs.com/bobobobobo/p/13101449.html
Copyright © 2011-2022 走看看