什么是事件,可以理解为当某个行为执行后发生的事,即为事件:
一个事件,可以拥有多个监听器,一个监听器只能监听一个事件。一个类可以监听多个事件即为事件订阅器。
而观察者则是事件的实现。它存在于事件之上,通俗讲,事件或者事件订阅器是通过观察者模式来实现的。
而监听只也是运用了设计模式中的单一职责则
模式: 一个类只做一件事。
事件:
传统的控制器里会把用户注册+发送邮件+发送信息的逻辑给写到一起,这样造成了代码的偶合度,单从代码的维护度来说不利于后期维护。所以事件的产生就是为了把逻辑抽离出来。各司其职。让控制器更干净的做它的事。
监听器:
监听器是负责监听某个事件发生。然后它负责处理某项事物。想象一下,用户注册成功后,会产生一个注册成功的事件,而这个监听器是负责发送邮件的,它就会根据用户的邮箱给用户发送一条注册成功的邮件。
根据上面所描述的。一个监听器只干一件事。你可以为一个事件类注册多个监听器,让这些监听器分别为用户发送邮箱和手机信息。甚至把用户注册信息写入至日志。
介绍了这么多,你已经迫不及待想写代码了吧。
创建事件与监听器
现在为我们用户注册成功后,创建一个事件
php artisan make:event UserStoreProcess
为事件创建属于它自己监听器,这个监听器,我们用来发送邮件给用户
php artisan make:listener SendSuccessfullyEmail --event=UserStoreProcess
这个监听器我们用来发送信息给用户手机
php artisan make:listener SendSuccessfullyMessage --event=UserStoreProcess
上面的命令执行完之后,你会发现你的
app
目下生成了两个文件夹 :Events
、Listeners
,目录里就是刚刚生成的事件类与监听器。
为事件注册监听器
编辑 app/Providers/EventServiceProvider
,加入以下内容
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
//用户注册成功事件
UserStoreProcess::class=>[
SendSuccessfullyEmail::class,
SendSuccessfullyMessage::class
]
];
这样就成功为事件注册了监听器
编辑事件类
即然我们创建的事件是为了给用户发送邮箱或手机号的。那么,我们应该在事件类里初始化一个User模型的实例。方便我们在监听器里获取模型的邮箱与手机号。UserStoreProcess
类:
use App\Models\User;
class UserStoreProcess {
use Dispatchable, InteractsWithSockets, SerializesModels;
public User $user;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(User $user) {
$this->$user = $user;
}
}
这样,调用事件时,就可以把当前注册的user实例传给事件类,事件类与监听器协作时,监听器就能拿到事件实例的一个字段属性user.
在编辑监听者之前,我们先来创建一个Mail
类:
php artisan make:mail UserSuccessfully --markdown=emails.users.successfully
运行此命令后,会生成 app/Mail/UserSuccessfully
,同时也会生成一个邮件的渲染模板:resources/views/emails/users/successfully.blade.php
编辑这邮件类
use App\Models\User;
class UserSuccessfully extends Mailable {
use Queueable, SerializesModels;
public $user;
public function __construct(User $user) {
$this->user = $user;
}
public function build() {
return $this->markdown('emails.users.successfully',[
'user'=>$this->user,
]);
}
}
上面的User实例,会在监听者里调用此类时传入。方便在模板里调用$user
的属性
编辑监听者
为了方便演示,就只展示发送邮件的过程,编辑 SendSuccessfullyEmail
类
use Illuminate\Support\Facades\Mail;
class SendSuccessfullyEmail {
//...
public function handle(UserStoreProcess $event) {
Mail::to($event->user->email)->send(new UserSuccessfully($event->user));
}
}
当然,这只是代码示例。真实情况下你得在.env配置文件里配置你的邮箱。这样才能正常发送邮箱给用户。
这个功能无非就是代替了手动发送邮件的功能。同理的。给用户发送手机信息也是同样的方法。这里就不再做演示
如何触发
在 UserController
创建用户方法中,如下代码
class UserController extends Controller {
public function store() {
//验证用户
//创建用户
event(new UserStoreProcess($user))
//返回值
}
}
这样,在用户创建成功后,将会把创建的用户实例传给事件类,让监听器来发送邮件和信息等操作。
事件订阅者
下面来讲讲事件订阅者,订阅者和事件监听是一个概念,只不过是一个监听器监听多个事件,哪个事件发生后,再处理哪个事件,至于用事件监听还是事件订阅者,根据你的个人习惯来
和创建事件与监听器方法一样。这里不过多赘述.下面来说下配置方法:
假现在有一个订阅者(监听器),监听登录成功事件,与退出登录事件。要求对对应事件做出监听处理
下面代码是引用自 laravel
中文社区
<?php
namespace App\Listeners;
class UserEventSubscriber
{
/**
* 处理用户登录事件。
*/
public function handleUserLogin($event) {}
/**
* 处理用户退出事件。
*/
public function handleUserLogout($event) {}
/**
* 为订阅者注册侦听器。
*
* @param \Illuminate\Events\Dispatcher $events
* @return void
*/
public function subscribe($events)
{
$events->listen(
'Illuminate\Auth\Events\Login',
[UserEventSubscriber::class, 'handleUserLogin']
);
$events->listen(
'Illuminate\Auth\Events\Logout',
[UserEventSubscriber::class, 'handleUserLogout']
);
}
}
上面的 Login
类与 Logout
类也可以定义为 你自己的事件类
注册事件订阅者
<?php
namespace App\Providers;
use App\Listeners\UserEventSubscriber;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
/**
* 应用的事件监听器映射
*
* @var array
*/
protected $listen = [
//
];
/**
* 被注册的订阅者类
*
* @var array
*/
protected $subscribe = [
UserEventSubscriber::class,
];
}
观察者
如果你想在模型中监听多个事件。这时就可以用到观察者
创建观察者
php artisan make:observer UserObserver --model=User
这样观察者即与模型关联起来
注册观察者
编辑 app/Providers/AppSericeProvider.php
<?php
namespace App\Providers;
use App\User;
use App\Observers\UserObserver;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* 运行所有应用.
*
* @return void
*/
public function boot()
{
// 为 User 模型注册观察者
User::observe(UserObserver::class);
}
/**
* 注册服务提供.
*
* @return void
*/
public function register()
{
//
}
}
观察者的使用方法是和事件一个道理。前面说过。事件的实现是在Observer的之下的。怎么用看你自己。