尝试说一说事件的使用

事件驱动编程是一种编程模式,其中的程序流由诸如用户动作(鼠标点击,按键)、传感器输出或来自其他程序/线程的消息等事件来决定确定。事件驱动编程是图形用户界面和其他应用程序(例如 JavaScript Web 应用程序)中使用的主要范例,用于执行某些操作来响应用户输入。

在 Laravel 里,有些事件是由她自动发起的,例如 Model 的 create、save、 update 或者是 delete 操作时,她会分别发起相应的事件,如果我们需要,可以监听这些事件,完成不同的需求。除了她自动发起的事件,我们也可以自己定义我们需要的事件以及监听器。

在应用中使用事件,是解耦应用的好方法,比如注册一位新用户。

Class UserController extends Controller
{
    public function store(Request $request)
    {
        $this->validate($request, [
            'name' => 'required',
            ...
            ...
        ]);

        $user = User::create($request->all());

        // 欢迎邮件
        if ($user->email) {
            Mail::to($user->email)->send(new Email($user));
        }

        // 推荐注册逻辑
        if ($request->get('invite_code')) {
            ...
            ...
        }

        // 通知运营
        $user->notify(new NewUser($user));

        // 各种各样的需求
        ...
        ...

        return Auth::login($user);
    }
}

在这个用户注册方法中,耦合了各种各样的逻辑,各种各样的需求,如果还要加一些奇怪的需求,这个方法就会越来越大,越来越长。

方法的关注点应该只有注册用户到应用中,它不应该关心其他逻辑。

这里我们通过 Laravel 的 artisan 命令,创建我们需要的事件类和与之对应的监听类。

php artisan make:event UserRegistered

php artisan make:listener SendWelcomeMail --event=UserRegistered

php artisan make:listener UpdateReferrer --event=UserRegistered

接下来,不要忘记到 EventServiceProvider 里的 $listen 属性中注册事件与监听器。

protected $listen = [ 
    UserRegistered::class => [ 
        SendWelcomeMail::class, 
        UpdateReferrer::class,
    ]
];

打开 app/Events/UserRegistered.php

public $user;

public function __construct(User $user)
{
    $this->user = $user;
}

接着打开 SendWelcomeMail.php

public function handle(UserRegistered $event)
{
    if (!$event->user->email) {
        return;
    }

    Mail::to($event->user->email)->send(new Email($event->user));
}

再打开 UpdateReferrer.php

public function handle(UserRegistered $event)
{
    ...
    ...
}

可以看到,通过事件驱动,我们让 UserController 的 store 方法,变得尽可能的少,并且专注于注册用户这件事上,其他逻辑由 UserRegistered 事件的监听器来负责完成。如果有新增加的需求,可是创建一个新的监听器来完成这件事。

当完成了事件与监听器的编写与注册之后,我们可以把它放进控制器逻辑。

public function store(Request $request)
{
    ...
    ...
    ...

    \event(new UserRegistered($user));
}

我个人比较喜欢把它放在模型事件中触发,可以尝试这么写。

class User extends Model
{
    public static function boot()
    {
        parent::boot();

        static::created(function (User $user) {
            \event(new UserRegistered($user));
        });
    }
}

我觉得使用 Laravel 的事件系统,可以让我们的作品变得更优雅,逻辑条理更清晰,也更具有拓展性。让每部分代码块,都知道自己是干什么的,要干什么,不需要关注与自己无关的事儿。代码块之间分工合作,你中有我,我中有你,最终把这件事情完成好。

本作品采用《CC 协议》,转载必须注明作者和本文链接
Hello。
本帖由系统于 5年前 自动加精
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 12

个人习惯建一个 observer 文件 ,然后在 AppServiceProvider 与 对应的 模型绑定

5年前 评论
finecho

:water_buffalo: :beers:

5年前 评论
Egfly

:water_buffalo: :beers:

5年前 评论

:water_buffalo: :beers:

5年前 评论

超哥也发表了这个文章。。。。内容一毛一样的。。。如果是转载的话请说明来源出处

5年前 评论

@cocoyo 超哥那篇也是我发的呀

5年前 评论
finecho

@zIym 你个冒牌 哈哈

5年前 评论

@Lhao 假粉丝

5年前 评论

大家好我是王源

4年前 评论
\event(new UserRegistered($user));

event是全局函数,为什么要加个\

4年前 评论
AbrahamGreyson 4年前

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