Thinkphp事件机制两种实现方式详解

目录
  • 一、通过监听
  • 二、通过订阅
    • 1、创建订阅类
    • 2、配置监听
    • 3、触发监听
    • 4、处理监听逻辑
      • 4.1 自动绑定
      • 4.2 手动绑定
  • 总结

事件机制的实现有两种途径:通过监听、通过订阅

一、通过监听

1、创建监听类:在命令行模式下进入框架根目录执行

php think make:listener <自定义的类名>

例如:

php think make:listener UserListener

执行之后将在<框架根目录>\app\listener\下生成UserListener这个类。

2、配置监听:在<框架根目录>\app\event.php这个文件的listen数组中配置UserListener这个类,如下:

'listen'    => [
    'testEvent' => ['app\listener\UserListener']
],

3、触发监听:在你需要触发监听的地方加入如下代码

event('testEvent');

注意:这里的参数testEvent即为事件名称,可随便定义,但必须要与在event.php文件里配置的键名一致。

触发监听时你可以带上第二个参数。通过第二个参数你可以把任何数据传递到UserListener这个类中,也就是handle方法的参数(不明白啥意思的结合下面的完整代码理解)。

4、处理监听逻辑:在UserListener类的handle方法中完成业务逻辑

完整代码如下

Other:一个用来测试的类

<?php
namespace app\controller;
class Other
{
    public function hello()
    {
        echo 'hello function';
    }
}

Index:触发监听的类

<?php
namespace app\controller;
use app\BaseController;
class Index extends BaseController
{
    public $name  = 'index';
    public function test1()
    {
        //触发监听事件,无参数
        event('testEvent');
    }
    public function test2()
    {
        //触发监听事件,传递字符串
        event('testEvent', 'hello');
    }
    public function test3()
    {
        //触发监听事件,传递自身类
        event('testEvent', $this);
    }
    public function test4()
    {
        //触发监听事件,传递其他类
        $other  = new Other();
        event('testEvent', $other);
    }
}

UserListener:事件监听类

<?php
namespace app\listener;
class UserListener
{
    /**
     * 事件监听处理
     *
     * @return mixed
     */
    public function handle($event)
    {
        //当调用Index类的test1方法时该代码有效,$event为null
        var_dump($event);
        //当调用Index类的test2方法时该代码有效,$event为字符串hello
        var_dump($event);
        //当调用Index类的test3方法时该代码有效,$event为Index类的实例
        //可以访问Index类的name变量
        echo $event->name;
        //当调用Index类的test4方法时该代码有效,$event为Other类的实例
        //可以调用Other类的hello方法
        echo $event->hello();
    }
}

二、通过订阅

1、创建订阅类

在命令行模式下进入框架根目录执行

php think make:subscribe <自定义的类名>

例如:

php think make:subscribe UserSubscribe

执行之后将在<框架根目录>\app\subscribe\下生成UserSubscribe这个类。

2、配置监听

在<框架根目录>\app\event.php这个文件的subscribe数组中配置UserSubscribe这个类,如下:

'subscribe' => ['app\subscribe\UserSubscribe'],

注意:为了测试效果,要把上面配置的UserListener从listen数组删除掉

3、触发监听

跟第一种途径一样

4、处理监听逻辑

处理监听的逻辑又有两种方法,我称之为自动绑定和手动绑定。手动绑定和自动绑定是互斥的,只能二选一。

4.1 自动绑定

在UserSubscribe类中添加ontestEvent方法,在该方法中完成业务逻辑。添加的方法名不能随意定义,规则是事件名称前面加上on。因为我们在event.php里定义的事件名称是testEvent,所以方法名就是ontestEvent(注意大小写)。监听方法定义之后就自动与事件绑定,所以我称之为自动绑定。

完整代码如下

Other和Index类的代码跟第一种途径一样

UserSubscribe:事件订阅类

<?php
namespace app\subscribe;
class UserSubscribe
{
    public function ontestEvent($user)
    {
        //当调用Index类的test1方法时该代码有效,$event为null
        var_dump($user);
        //当调用Index类的test2方法时该代码有效,$event为字符串hello
        var_dump($user);
        //当调用Index类的test3方法时该代码有效,$event为Index类的实例
        //可以访问Index类的name变量
        echo $user->name;
        //当调用Index类的test4方法时该代码有效,$event为Other类的实例
        //可以调用Other类的hello方法
        echo $user->hello();
    }
}

4.2 手动绑定

首先,创建事件类,负责处理具体的业务逻辑。在命令行模式下进入框架根目录执行:

php think make:event <自定义的类名>

例如:

php think make:event UserEvent

执行之后将在<框架根目录>\app\event\下生成UserEvent这个类。

再在该类中定义一个handle方法,该方法有一个传入参数。方法名和传入的参数名可以任意定义。具体的业务逻辑就可以放在handle方法里面处理。

然后,在UserSubscribe类中添加subscribe方法,该方法传入参数为 Event 对象。然后在该方法中将监听的事件绑定到UserEvent类的handle方法上。如下:

$event->listen('testEvent', [app('app\event\UserEvent'), 'handle']);

完整代码如下

Other和Index类的代码跟第一种途径一样

UserSubscribe:事件订阅类

<?php
declare (strict_types = 1);
namespace app\subscribe;
use think\Event;
class UserSubscribe
{
    public function subscribe(Event $event)
    {
        $event->listen('testEvent', [app('app\event\UserEvent'), 'handle']);
    }
}

UserEvent:事件处理类

<?php
declare (strict_types = 1);
namespace app\event;
class UserEvent
{
    public function handle($user)
    {
        //当调用Index类的test1方法时该代码有效,$user为null
        var_dump($user);
        //当调用Index类的test2方法时该代码有效,$user为字符串hello
        var_dump($user);
        //当调用Index类的test3方法时该代码有效,$user为Index类的实例
        //可以访问Index类的name变量
        echo $user->name;
        //当调用Index类的test4方法时该代码有效,$user为Other类的实例
        //可以调用Other类的hello方法
        echo $user->hello();
    }
}

总结

1、通过监听的方式,每个事件都需要定义一个监听类来处理监听逻辑,并且在event.php的listen数组中配置

2、通过订阅的方式,如果采用自动绑定,则需要在订阅类中为每个事件定义一个监听方法(方法名不能自己定义),不需要定义subscribe方法;如果采用手动绑定,则定义subscribe方法,并为每一个事件绑定负责处理业务逻辑的具体方法(方法名可以自己定义)

3、通过监听的方式中,事件类基本上可有可无,因为创建的监听类本来就是专门处理对应的事件的业务逻辑的。并且监听类可以用事件类代替。

4、通过订阅的方式中,如果采用自动绑定,事件类也没有必要,因为在订阅类中为每个事件定义的监听方法本来就是专门处理对应的事件的业务逻辑的。如果采用手动绑定,也可以把监听方法写在订阅类中,那么事件类也就没必要了。但是个人认为手动绑定还是使用事件类比较好。订阅类只负责绑定,事件类负责处理具体业务逻辑,这样结构上比较清晰

5、其实通过监听的方式中,监听类(例子中的UserListener)可以替换成其他命名空间下的其他类,只要该类有一个handle方法就行,比如事件类。替换之后记得要在event.php配置文件中做对应修改。同理,通过订阅的方式中,也可以将订阅类(例子中的UserSubscribe)直接替换为其他类,但是要记得自动绑定需要在该类下有符合命名规则的方法,手动绑定需要在该类下有一个subscribe方法

以上就是Thinkphp事件机制两种实现方式详解的详细内容,更多关于Thinkphp事件机制的资料请关注我们其它相关文章!

时间: 2022-09-17

PHP实现事件机制的方法

本文实例讲述了PHP实现事件机制的方法.分享给大家供大家参考.具体如下: <?php /** * 事件 */ class Event { private $callbacks = array(); private $holder; function __construct() { $bt = debug_backtrace(); if (count($bt) < 2) { $this->holder = null; return; } $this->holder = &$b

PHP 事件机制(2)

复制代码 代码如下: <?php class Event extends stdClass{ public $target=null; public $type=null; /** * 创建事件 * @param string $type */ public function __construct($type){ $this->type=trim($type); } /** * 得到事件字符串 */ public function __toString(){ return $this->

基于PHP实现的事件机制实例分析

本文实例讲述了基于PHP实现的事件机制.分享给大家供大家参考.具体分析如下: 内置了事件机制的语言不多,php也没有提供这样的功能.事件(Event)说简单了就是一个Observer模式,实现起来很容易.但是有所不同的是,事件的监听者谁都可以加,但是只能由直接包含它的对象触发.这就有一点点难度了.php有一个debug_backtrace函数,可以得到当前的调用栈,由此可以找到判断调用事件触发函数的对象是不是直接包含它的对象的办法. <?php /** * 事件 * * @author xiez

PHP实现事件机制实例分析

本文实例讲述了PHP实现事件机制的方法.分享给大家供大家参考.具体分析如下: 内置了事件机制的语言不多,php也没有提供这样的功能.事件(Event)说简单了就是一个Observer模式,实现起来很容易.但是有所不同的是,事件的监听者谁都可以加,但是只能由直接包含它的对象触发.这就有一点点难度了.php有一个debug_backtrace函数,可以得到当前的调用栈,由此可以找到判断调用事件触发函数的对象是不是直接包含它的对象的办法. <?php /** * 事件 * * @author xiez

深入解析PHP的Yii框架中的event事件机制

事件 事件可以将自定义代码"注入"到现有代码中的特定执行点.附加自定义代码到某个事件,当这个事件被触发时,这些代码就会自动执行.例如,邮件程序对象成功发出消息时可触发 messageSent 事件.如想追踪成功发送的消息,可以附加相应追踪代码到messageSent 事件. Yii 引入了名为 yii\base\Component 的基类以支持事件.如果一个类需要触发事件就应该继承 yii\base\Component 或其子类. Yii的event机制 YII的事件机制,是其比较独特

深入解析PHP的Laravel框架中的event事件操作

有时候当我们单纯的看 Laravel 手册的时候会有一些疑惑,比如说系统服务下的授权和事件,这些功能服务的应用场景是什么,其实如果没有经历过一定的开发经验有这些疑惑是很正常的事情,但是当我们在工作中多加思考会发现有时候这些服务其实我们一直都见过.下面就事件.事件监听举一个很简单的例子你就会发现. ​ 这个例子是关于文章的浏览数的实现,当用户查看文章的时候文章的浏览数会增加1,用户查看文章就是一个事件,有了事件,就需要一个事件监听器,对监听的事件发生后执行相应的操作(文章浏览数加1),其实这种监听

深入解析PHP的Yii框架中的缓存功能

数据缓存是指将一些 PHP 变量存储到缓存中,使用时再从缓存中取回.它也是更高级缓存特性的基础,例如查询缓存和内容缓存. 如下代码是一个典型的数据缓存使用模式.其中 $cache 指向缓存组件: // 尝试从缓存中取回 $data $data = $cache->get($key); if ($data === false) { // $data 在缓存中没有找到,则重新计算它的值 // 将 $data 存放到缓存供下次使用 $cache->set($key, $data); } // 这儿

解析PHP的Yii框架中cookie和session功能的相关操作

Sessions 和 请求 和 响应类似, 默认可通过为yii\web\Session 实例的session 应用组件 来访问sessions. 开启和关闭 Sessions 可使用以下代码来开启和关闭session. $session = Yii::$app->session; // 检查session是否开启 if ($session->isActive) ... // 开启session $session->open(); // 关闭session $session->clo

Yii框架中sphinx索引配置方法解析

本文实例讲述了Yii框架中sphinx索引配置方法.分享给大家供大家参考,具体如下: 请先将var/test/documents.sql导入数据库,并配置好以下的MySQL用户密码数据库 #源定义 source mysql { type = mysql sql_host = localhost sql_user = root sql_pass = root sql_db = yii2 sql_port = 3306 sql_query_pre = SET NAMES utf8 sql_query

JavaScript中全选、全不选、反选、无刷新删除、批量删除、即点即改入库(在yii框架中操作)的代码分享

效果展示: 代码实现: 控制器 <?php namespace app\controllers; use Yii; use yii\filters\AccessControl; use yii\web\Controller; use yii\filters\VerbFilter; use app\models\LoginForm; use app\models\ContactForm; //use yii\db\ActiveRecord; use yii\data\Pagination; use

YII框架中使用memcache的方法详解

本文实例讲述了YII框架中使用memcache的方法.分享给大家供大家参考,具体如下: yii中可以很方便的使用memcache 一.配置 在main.php的components中加入cache配置 array( 'components'=>array( 'cache'=>array( 'class'=>'CMemCache', 'servers'=>array( array( 'host'=>'server1', 'port'=>11211, 'weight'=&g

Yii框架中memcache用法实例

本文实例讲述了Yii框架中memcache用法.分享给大家供大家参考.具体分析如下: 在现在的公司用的是YII的框架,接触到的东西也比较多,可以学到的东西也比较多,在以前的公司没有接触过memcache,只是听过,但是从来没有真正用过.现在终于有机会使用一下了,就以我做的项目为例吧! 我做的项目是一个手机排行榜,但是排行榜每隔15分钟刷新一次啊,排行榜有一个前三名,可能前15分钟这三个人是前三名,也许下一个15分钟又是别人前三名了,产品要求,这些人中只要是前三名的都要发奖品,思考了好久,最终决定

Yii框架中jquery表单验证插件用法示例

本文实例讲述了Yii框架中jquery表单验证插件用法.分享给大家供大家参考,具体如下: 运行效果图如下: 视图层: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtm

YII框架中搜索分页jQuery写法详解

控制层 use frontend\models\StudUser; use yii\data\Pagination; use yii\db\Query; /** * 查询 * */ public function actionSearch() { //接值 $where=Yii::$app->request->get(); //实例化query $query=new Query(); $query->from('stud_user'); //判断 if(isset($where['sex