初识事件监听

前言

《L02 Laravel 教程 - Web 开发实战进阶 ( Laravel 8.x )》的3.7节——认证后的提示中就用到了事件监听。

虽然laravel提供了一套成熟的注册登录的功能。在注册时,需要用户邮件认证,但是当用户点击认证邮件中的链接后,就注册成功并跳转到主页。但是问题是没有任何反馈,这样的体验很不好。邮件认证的逻辑在vendor/laravel/ui/auth-backend/VerifiesEmails.php中,理论上只要修改验证成功后的逻辑就好了,但是课程中提到修改vendor/laravel/ui/auth-backend/VerifiesEmails.php文件是不可取的。那该怎么办呢?就涉及到今天这篇博客的主题了——事件监听。通过对Verified事件进行监听,就可以轻松的解决这个问题。

两个例子:

教程中并没有对事件监听进行展开,文档写的也很抽象,还是通过两个例子来认识事件监听吧:
1. 实现文章浏览的计数。
场景:用户浏览文章后,浏览数+1。
具体实现:
1.1 注册事件和监听器
App\Providers\EventServiceProvider中注册所有的事件监听者。具体如下:

protected $listen = [
        'App\Events\BlogView' => [
            'App\Listeners\BlogViewListener',
        ],
    ];
// 键为事件,值为监听器。

1.2 生成事件和监听器

在命令行中执行php artisan event:generate,此命令将生成 EventServiceProvider 中列出的、尚不存在的任何事件或监听器。

1.2.1 自动生成的事件文件app/Events/BlogView.php如下:

<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class BlogView
{
    use Dispatchable, InteractsWithSockets, SerializesModels;
    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }
    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    {
        return new PrivateChannel('channel-name');
    }
}

1.2.2 自动生成的监听器文件app/Listeners/BlogViewListener.php如下:

<?php
namespace App\Listeners;
use App\Events\BlogView;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
class BlogViewListener
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }
    /**
     * Handle the event.
     *
     * @param  \App\Events\BlogView  $event
     * @return void
     */
    public function handle(BlogView $event)
    {
        //
    }
}

1.3 定义事件:考虑到要处理帖子模型,修改BlogView.php的构造器,在实例化的时候就将post实例赋值给post属性。(对事件的处理视具体情况而定)

<?php
namespace App\Events;
use App\Models\Post;
...
class BlogView
{
    ...
    public $post;
    public function __construct(Post $post)
    {
        $this->post = $post;
    }
    ...
}

1.4 定义监听器:事件发生时,浏览数+1。

<?php
namespace App\Listeners;
...
class BlogViewListener
{
    ...
    public function handle(BlogView $event)
    {
        $post = $event->post;
        dd('浏览数+1!');
    }
}

1.5 触发事件:当用户查看文章的时候就触发。


<?php

namespace App\Http\Controllers;
use App\Models\Post;
// 注意这里需要引入BlogView类。
use App\Events\BlogView;
...
class PostController extends Controller
{
    ...
    public function show(){
        $post = Post::find(1);
        // 触发事件
        event(new BlogView($post));
        return view('post.show');
    }
}

1.6 结果:

初识事件监听

2. 物流发货后,发短信通知用户。

前辈的这篇博客——记录下学习笔记(Laravel 中的事件监听)写的已经很清楚了,就不再赘言。

什么是事件?

在第一个例子中,事件是查看文章。

在第一个例子中,事件是物流发货。

感觉事件可以是任何动作。

什么是监听器?

不太好下定义,但是可以通过监听器的功能来理解什么是监听器。当监听器用于监听事件,事件一旦触发,就执行相应的逻辑。

具体步骤

1. 注册事件和监听器。

2. 生成事件和监听器。

3. 定义事件和监听器。

4. 触发事件。

注意事项

1. 如果希望再某个类的某个动作中触发事件,需要在该类中引入事件类。例如:在第一个例子中,是在PostController类的show动作中触发了事件,所以需要在PostController类中引入BlogView事件类:

<?php
// 注意这里需要引入BlogView类。
use App\Events\BlogView;
...

class PostController extends Controller
{
    ...
}

2. 一个事件可以由多个监听器监听。在第二个例子中,物流发货后,我希望可以同时发送短信和微信通知用户,可以通过定义两个监听器实现:

protected $listen = [

  'App\Events\OrderEvent' => [

      'App\Listeners\sendModel',

      'App\Listeners\sendPhone',

  ]

];

感谢laravel-china社区

laravel框架很多功能都封装好了,所以在学课程的3.7节时,就感觉事件监听不难。但是我去看文档的时候,又看的迷迷糊糊的。不过幸好有很多前辈在这个社区写过很多优秀的,关于事件监听的博客,所以我很容易就收集到了例子。在这些例子中才对事件监听有一点感觉,才知道该怎么用。

参考:

1. Laravel 中的事件监听

2. 记录下学习笔记(Laravel 中的事件监听)

3. 文档

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 2

事件监听的目的是为了解决相同场景的代码耦合

试想:用户在回复帖子、发布文章、文章被点赞、回帖被采纳、回帖被楼主回复时,都需要为用户添加积分,并且通知用户,如果按照往常的逻辑,要为这些业务的都分别添加用户增长积分,通知用户。

这样并不有利维维护,一旦业务需求发生了修改,那要分别去改这些处的代码。

有了事件监听就很简单了,只需要使用 event 方法,在 Listener 中来处理这些业务逻辑,这样一旦业务发生修改,只需要修改 Listener 就可以了,代码非常简洁。

2年前 评论
Moonshadow2333 (楼主) 2年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!