ThinkPHP6 事件的简单应用

hykeda11个月前ThinkPHP878

一、序章

ThinkPHP6的手册中关于【事件】章节的介绍都是直接文字说明,给出创建的类文件,并没有一个好的示例来进行补充说明。

对于刚接触【事件】的同学在阅读理解上增加了一点点困难,本文就在此结合示例简单叙述下。


二、事件

事件的使用分两种方式,一个是不使用事件类,另一个使用事件类。


1、不使用事件类

(1)使用 php think 创建一个监听类

php think make:listener UserListener


(2)打开 UserListener 类文件,echo 出 【UserListener 监听处理】,成功输入表示进入到了监听内部。

<?php
declare (strict_types = 1);
 
namespace app\listener;
 
class UserListener
{
    /**
     * 事件监听处理
     *
     * @return mixed
     */
    public function handle($event)
    {
        // 事件监听处理
        echo $event.': UserListener 监听处理<br>';
    }
}

(3)注册监听。找到并打开【路径:根目录/app/event.php】event.php文件,添加内容如下:

<?php
// 事件定义文件
return [
    'bind'      => [
    ],
 
    'listen'    => [
        'AppInit'  => [],
        'HttpRun'  => [],
        'HttpEnd'  => [],
        'LogLevel' => [],
        'LogWrite' => [],
        //注册监听类
        'User' => ['app\listener\UserListener'],
    ],
 
    'subscribe' => [
    ],
];

(4)触发事件。在需要触发的业务代码中调用。

<?php
/**
 * Created by PhpStorm
 * Author: fengzi
 * Date: 2023/12/15
 * Time: 17:24
 */
 
namespace app\admin\controller;
 
use think\facade\Event;
 
class LoginController extends AdminBaseController
{
    public function initialize()
    {
        parent::initialize(); // TODO: Change the autogenerated stub
    }
 
    public function login()
    {
        echo "登录成功<br>";
        
        // 触发User事件
        Event::trigger('User', '第一次');
 
        // 使用助手函数触发User事件
        event('User', '第二次');
    }
}

(5)使用效果展示。图中分别展示了在第(4)步中的三次输出,说明调用成功。User事件调用了两次,所以输出了两次。

0d376fb3d16cb3057457cc03456e4745_647d7ee69d1f5a4d1655951761f87206.png

(6)上面的示例为自动注册监听。还有一种是自己手动注册监听。前面(1)和(2)的步骤都是一样的,这里就不在重复贴代码了,到第(3)步时不需要注册。

<?php
// 事件定义文件
return [
    'bind'      => [
    ],
 
    'listen'    => [
        'AppInit'  => [],
        'HttpRun'  => [],
        'HttpEnd'  => [],
        'LogLevel' => [],
        'LogWrite' => [],
    ],
 
    'subscribe' => [
    ],
];

(7)触发事件。在需要触发的业务代码中手动注册并调用。

<?php
/**
 * Created by PhpStorm
 * Author: fengzi
 * Date: 2023/12/15
 * Time: 17:24
 */
 
namespace app\admin\controller;
 
use think\facade\Event;
 
class LoginController extends AdminBaseController
{
    public function initialize()
    {
        parent::initialize(); // TODO: Change the autogenerated stub
    }
 
    public function login()
    {
        echo "登录成功<br>";
 
        // 注册User事件
        Event::listen('User', 'app\listener\UserListener');
 
        echo '注册成功,触发User事件<br>';
 
        // 触发User事件
        Event::trigger('User', '第一次');
 
        // 使用助手函数触发User事件
        event('User', '第二次');
    }
}

(8)使用效果展示。

89a16242a508398ad11d6a63959a8af6_3ab1ae9deff8d3f891f9912c006b882d.png


(9)总结

不管是自动注册还是手动注册,都要注意绑定的事件名称要相同,不然无法监听成功。

a12597525fc9028e5e21281453879595_bafc255291fe54a0588316e891d4b538.png

449fece571d19ba075a6e5514cc69a8b_f8ef131f96ed6814597f4e7b155e0cbd.png


2、使用事件类

(1)创建事件类文件

php think make:event UserEvent


(2)在【根目录/app/event】在找到UserEvent文件,修改成如下内容:

<?php
declare (strict_types = 1);
 
namespace app\event;
 
class UserEvent
{
    private $name;
 
    public function __construct(string $name)
    {
        $this->name = $name;
    }
 
    /**
     * @return string
     */
    public function getName(): string
    {
        return $this->name;
    }
}

(3)在【根目录/app/event.php】文件中添加UserEvent的事件绑定

<?php
// 事件定义文件
return [
    'bind'      => [
        'userEvent' => 'app\event\UserEvent',
    ],
 
    'listen'    => [
        'AppInit'  => [],
        'HttpRun'  => [],
        'HttpEnd'  => [],
        'LogLevel' => [],
        'LogWrite' => [],
    ],
 
    'subscribe' => [
    ],
];

(4)创建事件监听

php think make:listener UserListener

(5)在【根目录/app/event.php】文件中注册UserListener的监听类

<?php
// 事件定义文件
return [
    'bind'      => [
        'userEvent' => 'app\event\UserEvent',
    ],
 
    'listen'    => [
        'AppInit'  => [],
        'HttpRun'  => [],
        'HttpEnd'  => [],
        'LogLevel' => [],
        'LogWrite' => [],
        //注册监听类
        'UserEvent' => ['app\listener\UserListener'],
    ],
 
    'subscribe' => [
    ],
];

(6)打开 UserListener.php 文件,修改内容如下:

<?php
declare (strict_types = 1);
 
namespace app\listener;
 
class UserListener
{
    /**
     * 事件监听处理
     *
     * @return mixed
     */
    public function handle($event)
    {
        echo $event->getName().'<br>';
    }
}

(7)触发事件。在需要触发的业务代码中调用。

<?php
/**
 * Created by PhpStorm
 * Author: fengzi
 * Date: 2023/12/15
 * Time: 17:24
 */
namespace app\admin\controller;
 
use app\event\UserEvent;
use think\facade\Event;
 
class LoginController extends AdminBaseController
{
    public function initialize()
    {
        parent::initialize(); // TODO: Change the autogenerated stub
    }
 
    public function login()
    {
        echo "登录成功<br>";
 
        /**
         * 第一种触发User事件写法
         * 参数1:监听名称
         *   必须保证和event.php文件中的【listen】数组中的键名一致,否则无法调用成功。
         *   本示例中event.php文件里配置的键值是【UserEvent】
         * 参数2:事件
         *   事件对象
         */
        Event::trigger('UserEvent', new UserEvent('张三'));
 
        /**
         * 第二种触发User事件写法
         * 这种写法必须保证和event.php文件中的【bind】和【listen】的键名一致,否则无法调用成功。
         */
        Event::trigger(new UserEvent('李四'));
    }
}

(8)运行结果展示。

88c6a1a4cb5ac5e103a6ca6a1e0680eb_f6460bf57bb64308c1a1b6c12c3013ca.png

(9)总结


个人理解:事件类好比发邮件这个动作,发邮件的一系列动作都写在了事件类中(其实可以看做一个独立的邮件类文件)。

在你需要发送邮件的时候通过【Event::trigger()】触发一下,就可以发送邮件了。


三、事件订阅

1、事件订阅

这种方式相当于把事件写在了订阅类中,订阅类中的一个方法就是一个事件。


(1)使用 php think 创建一个订阅类

php think make:subscribe UserSubscribe

(2)打开 UserSubscribe 类文件,修改内容如下:

<?php
declare (strict_types = 1);
 
namespace app\subscribe;
 
class UserSubscribe
{
    public function onName($event)
    {
        echo $event.'<br>';
    }
}

(3)注册订阅。找到并打开【地址:根目录/app/event.php】event.php文件,添加内容如下:

<?php
// 事件定义文件
return [
    'bind'      => [
    ],
 
    'listen'    => [
        'AppInit'  => [],
        'HttpRun'  => [],
        'HttpEnd'  => [],
        'LogLevel' => [],
        'LogWrite' => [],
    ],
 
    'subscribe' => [
        'app\subscribe\UserSubscribe',
    ],
];

(4)触发事件。在需要触发的业务代码中调用。

<?php
/**
 * Created by PhpStorm
 * Author: fengzi
 * Date: 2023/12/15
 * Time: 17:24
 */
namespace app\admin\controller;
 
use think\facade\Event;
 
class LoginController extends AdminBaseController
{
    public function initialize()
    {
        parent::initialize(); // TODO: Change the autogenerated stub
    }
 
    public function login()
    {
        echo "登录成功<br>";
 
        /**
         * 手动注册订阅
         * 如果手动注册订阅类,则不需要在配置文件(event.php)中注册,这步按需使用。
         */
        Event::subscribe('app\subscribe\UserSubscribe');
 
        /**
         * 触发事件
         * 参数1:事件名称,必须与[app\subscribe\UserSubscribe.php]文件中定义的方法名称相同(方法名要除去固定格式on)
         *   例如:事件方法名称为:onName,则参数1的标识名称就为:Name
         * 参数2:传递给事件处理函数的数据
         */
        Event::trigger('Name', '张三,33岁');
 
        /**
         * 触发事件(使用助手函数)
         * 参数1:事件名称,必须与[app\subscribe\UserSubscribe.php]文件中定义的方法名称相同(方法名要除去固定格式on)
         *   例如:事件方法名称为:onName,则参数1的标识名称就为:Name
         * 参数2:传递给事件处理函数的数据
         */
        event('Name', '李四,34岁');
    }
}

(5)结果展示

94f0d0f7ed711ab876cd0e4e434cbadc_ad20eacfa521bbae90d36019869dfbd9.png

2、自定义订阅

这种方式相当于在自定义订阅中调用事先定义好的事件类(项目根目录/app/event下的文件),然后自行绑定调用关系。

(1)使用 php think 创建一个事件类

php think make:event UserEvent

(2)打开 UserEvent 类文件,修改内容如下:

<?php
declare (strict_types = 1);
 
namespace app\event;
 
class UserEvent
{
    /**
     * @param $params
     * @return mixed
     */
    public function getName($params)
    {
        // 打印name字段的数据
        echo $params['name'];
 
        // 返回传入的数据
        return $params;
    }
 
    /**
     * @param $params
     * @return mixed
     */
    public function getAge($params)
    {
        // 打印age字段的数据
        echo $params['age'];
 
        // 返回传入的数据
        return $params;
    }
}

(3)使用 php think 创建一个订阅类

php think make:subscribe UserSubscribe

(4)打开 UserSubscribe 类文件,修改内容如下:

<?php
declare (strict_types = 1);
 
namespace app\subscribe;
 
use app\event\UserEvent;
use think\Event;
 
class UserSubscribe
{
    /**
     * 自定义订阅
     * @param Event $event
     * @return void
     * @Author: fengzi
     */
    public function subscribe(Event $event)
    {
        // UserEvent::class 为第(2)步中创建的事件类,getName为事件类中的方法名称
        $event->listen('name', [UserEvent::class, 'getName']);
 
        // UserEvent::class 为第(2)步中创建的事件类,getAge为事件类中的方法名称
        $event->listen('age', [UserEvent::class, 'getAge']);
    }
}

(5)注册订阅类。配置注册文件event.php,内容如下:

<?php
// 事件定义文件
return [
    'bind'      => [
    ],
 
    'listen'    => [
        'AppInit'  => [],
        'HttpRun'  => [],
        'HttpEnd'  => [],
        'LogLevel' => [],
        'LogWrite' => [],
    ],
 
    'subscribe' => [
        'app\subscribe\UserSubscribe',
    ],
];

(6)触发订阅,在业务流程中触发订阅。

<?php
/**
 * Created by PhpStorm
 * Author: fengzi
 * Date: 2023/12/15
 * Time: 17:24
 */
namespace app\admin\controller;
 
use think\facade\Event;
 
class LoginController extends AdminBaseController
{
    public function initialize()
    {
        parent::initialize(); // TODO: Change the autogenerated stub
    }
 
    public function login()
    {
        echo "登录成功<br>";
 
        /**
         * 触发订阅
         * 参数1:订阅名称,名称必须要跟订阅类(UserSubscribe)中listen调用的监听名称一致
         * 参数2:传递给订阅方法的参数
         */
        $name = Event::trigger('name', ['name'=>'李四', 'age'=>30]);
 
        /**
         * 触发订阅
         * 参数1:订阅名称,名称必须要跟订阅类(UserSubscribe)中listen调用的监听名称一致
         * 参数2:传递给订阅方法的参数
         */
        $age = event('age', ['name'=>'王五', 'age'=>45]);
 
        /**
         * 打印返回数据
         * 订阅是可以返回数据的
         */
        dd($name, $age);
    }
}

(7)运行程序,展示结果。

8fab55658ffc84ed2809e9cad2bd72dc_f81eabbd05081d216caadc674ac68915.jpeg

(8)总结


简单理解:

1、事件订阅就是把订阅类中的方法当作事件来用,一个方法就是一个事件,

调用订阅类中的方法就是调用事件,把相关的业务写在订阅方法中就可以了。

2、自定义订阅时,订阅类其实只是个桥梁,起到绑定具体事件类的作用。具体的业务还是写在事件类中。

3、自定义订阅中可以绑定多个事件类,每个绑定都可以取一个监听名称,

业务调用时使用Event::trigger('监听名称')来调用。


原文链接:https://blog.csdn.net/melist_one/article/details/135204444


标签: 事件thinkphp6

相关文章

thinkphp5 报错级别设置,屏蔽警告

本着严谨的原则,5.0版本默认情况下会对任何错误(包括警告错误)抛出异常,如果不希望如此严谨的抛出异常,可以在应用公共函数文件中(common.php)或者配置文件中使用error_report...

Thinkphp6中在构造函数中返回json数据

return json($arr)->send();如果直接在构造函数中使用return json()是不会返回json格式的数据的。必须调用send方法。...

记录thinkphp3.13移植到php7过程

随着php7的兴起,越来越多的公司用php7了,下面记录一次thinkphp3.1.3项目移植到php7解决兼容性的过程。 先在thinkphp...

Thinkphp5 记录点,注意点

json对象转成数组 先用$flag->getContent() $flag = json_decode($flag->getContent(),true); 控制器: 1、当控制器...

thinkphp5页面出现500服务器内部错误

    最近写项目发现页面显示正常,控制器单独输出调试都正常,数据返回了,但还是报错get请求报错500服务器内部错误。  &nbs...

关于thinkphp6 where以数组形式查询,其中有or,and的处理

最近在写tp6的查询语句时,如果查询条件以数组形式传入,比如:$where[] = ['id','=',$id]; $where[] =...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。