Laravel中的自定义事件

本文深入探讨Laravel框架中的事件管理,介绍如何利用观察者模式创建自定义事件和侦听器,实现系统组件的解耦。同时,讲解了事件订阅者的作用及其实现方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在本文中,我们将探讨Laravel中事件管理的基础。 这是您作为开发人员应该在所需框架中拥有的重要功能之一。 在继续进行时,我们还将抓住这个机会,创建一个自定义事件和侦听器的真实示例,这也是本文的最终目标。

Laravel中事件的概念基于一种非常流行的软件设计模式-观察者模式。 在这种模式下,系统应该在发生某些事件时引发事件,并且您可以定义侦听器,以侦听这些事件并做出相应的反应。 这是一个非常有用的功能,它允许您解耦系统中的组件,否则将导致紧密耦合的代码。

例如,假设您想在有人登录到您的站点时通知系统中的所有模块。 因此,无论是发送电子邮件或应用内通知,还是任何想要对该登录事件做出反应的东西,它都使他们能够对这个登录事件做出反应。

事件和侦听器的基础

在本节中,我们将探讨Laravel在核心框架中实现事件和侦听器的方式。 如果您熟悉Laravel的体系结构,您可能知道Laravel实现了服务提供程序的概念,该服务提供程序允许您将不同的服务注入到应用程序中。

同样,Laravel提供了内置的EventServiceProvider.php类,该类允许我们为应用程序定义事件侦听器映射。

继续并拉入app/Providers/EventServiceProvider.php文件。

<?php
namespace App\Providers;
use Illuminate\Support\Facades\Event;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
    /**
     * The event listener mappings for the application.
     *
     * @var array
     */
    protected $listen = [
        'App\Events\SomeEvent' => [
        'App\Listeners\EventListener',
        ],
    ];
    /**
     * Register any events for your application.
     *
     * @return void
     */
    public function boot()
    {
        parent::boot();
        //
    }
}

让我们仔细看看$listen属性,该属性使您可以定义事件和关联的侦听器的数组。 数组键对应于系统中的事件,其值对应于在系统中引发相应事件时将触发的侦听器。

我更喜欢通过一个真实的例子来进一步说明它。 您可能知道,Laravel提供了一个内置的身份验证系统,该系统促进了登录,注册等功能。

假设您要在有人登录应用程序时发送电子邮件通知(作为安全措施)。 如果Laravel不支持事件侦听器功能,则您可能最终已经编辑了核心类或其他方法来插入发送电子邮件的代码。

实际上,Laravel可以帮助您使用事件侦听器解决此问题,因此您会感到幸运。 让我们将app/Providers/EventServiceProvider.php文件修改为如下所示。

<?php
namespace App\Providers;
use Illuminate\Support\Facades\Event;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
    /**
     * The event listener mappings for the application.
     *
     * @var array
     */
    protected $listen = [
        'Illuminate\Auth\Events\Login' => [
        'App\Listeners\SendEmailNotification',
        ],
    ];
    /**
     * Register any events for your application.
     *
     * @return void
     */
    public function boot()
    {
        parent::boot();
        //
    }
}

Illuminate\Auth\Events\Login是一个事件,当有人登录到应用程序时, Auth插件将引发该事件。 我们已将该事件绑定到App\Listeners\SendEmailNotification侦听器,因此将在登录事件时触发。

当然,您首先需要定义App\Listeners\SendEmailNotification侦听器类。 与往常一样,Laravel允许您使用artisan命令创建侦听器的模板代码。

php artisan event:generate

此命令生成$listen属性下列出的事件和侦听器类。

在我们的例子中, Illuminate\Auth\Events\Login事件已经存在,因此它仅创建App\Listeners\SendEmailNotification侦听器类。 实际上,如果一开始就不存在Illuminate\Auth\Events\Login事件类,那么它也会创建它。

让我们看一下在app/Listeners/SendEmailNotification.php创建的侦听器类。

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

每当触发侦听器时,便会使用适当的依赖项调用该handle方法。 在我们的例子中, $event参数应包含有关登录事件的上下文信息,即登录的用户信息。

并且我们可以使用$event对象在handle方法中进行进一步处理。 在本例中,我们希望将电子邮件通知发送给已登录的用户。

修改后的handle方法可能类似于:

public function handle(Login $event)
{
    // get logged in user's email and username
    $email = $event->user->email;
    $username = $event->user->name;
    
    // send email notification about login
}

这就是您应该使用Laravel中的事件功能的方式。 从下一部分开始,我们将继续创建自定义事件和关联的侦听器类。

创建自定义事件

我们将在本示例中使用的示例场景是这样的:

  • 应用程序需要在某些时候清除系统中的缓存。 当应用程序执行上述操作时,我们将引发CacheClear事件以及上下文信息。 我们将传递缓存组键以及已清除的事件。
  • 系统中的其他模块可能会监听CacheClear事件,并希望实现预热相关缓存的代码。

让我们重新访问app/Providers/EventServiceProvider.php文件,并注册我们的自定义事件和侦听器映射。

<?php
namespace App\Providers;
use Illuminate\Support\Facades\Event;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
    /**
     * The event listener mappings for the application.
     *
     * @var array
     */
    protected $listen = [
        'App\Events\ClearCache' => [
        'App\Listeners\WarmUpCache',
        ],
    ];
    /**
     * Register any events for your application.
     *
     * @return void
     */
    public function boot()
    {
        parent::boot();
        //
    }
}

如您所见,我们已经在$listen属性下定义了App\Events\ClearCache事件和关联的侦听器类App\Listeners\WarmUpCache

接下来,我们需要创建关联的类文件。 回想一下,您始终可以使用artisan命令来生成基本模板代码。

php artisan event:generate

那应该已经在app/Events/ClearCache.php创建了事件类,并且在app/Listeners/WarmUpCache.php创建了侦听器类。

进行一些更改后, app/Events/ClearCache.php类应如下所示:

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

您可能已经注意到,我们添加了一个新属性$cache_keys ,该属性将用于保存将与事件一起传递的信息。 在我们的例子中,我们将传递刷新的缓存组。

接下来,让我们在app/Listeners/WarmUpCache.php上使用更新后的handle方法查看app/Listeners/WarmUpCache.php

<?php
namespace App\Listeners;
use App\Events\ClearCache;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class WarmUpCache
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }
    /**
     * Handle the event.
     *
     * @param  ClearCache  $event
     * @return void
     */
    public function handle(ClearCache $event)
    {
        if (isset($event->cache_keys) && count($event->cache_keys)) {
            foreach ($event->cache_keys as $cache_key) {
                // generate cache for this key
                // warm_up_cache($cache_key)
            }
        }
    }
}

调用侦听器时, handle方法将与关联事件的实例一起传递。 在我们的例子中,应该是ClearCache事件的实例,该实例将作为第一个参数传递给handle方法。

接下来,只需要遍历每个缓存键并预热关联的缓存即可。

现在,我们已经准备就绪,可以进行测试。 让我们在app/Http/Controllers/EventController.php快速创建一个控制器文件,以演示如何引发事件。

<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Library\Services\Contracts\CustomServiceInterface;
use App\Post;
use Illuminate\Support\Facades\Gate;
use App\Events\ClearCache;
class EventController extends Controller
{
    public function index()
    {
        // ...
        
        // you clear specific caches at this stage
        $arr_caches = ['categories', 'products'];
        
        // want to raise ClearCache event
        event(new ClearCache($arr_caches));
        
        // ...
    }
}

首先,我们在创建ClearCache事件的实例时传递了一组缓存键作为第一个参数。

事件助手功能用于从应用程序中的任何位置引发事件。 引发事件时,Laravel会调用所有侦听器来监听该特定事件。

在我们的示例中,将App\Listeners\WarmUpCache侦听器设置为侦听App\Events\ClearCache事件。 因此,当从控制器引发事件时,将调用App\Listeners\WarmUpCache侦听App\Listeners\WarmUpCachehandle方法。 剩下的就是预热已清除的缓存!

这样便可以在应用程序中创建自定义事件并使用它们。

什么是事件订阅者?

事件订阅者允许您在单个位置订阅多个事件侦听器。 无论您是想对事件侦听器进行逻辑分组还是要在一个地方包含不断增长的事件,它都是您要寻找的事件订阅者。

如果我们使用事件订阅者实现了本文到目前为止讨论的示例,则它可能看起来像这样。

<?php
// app/Listeners/ExampleEventSubscriber.php
namespace App\Listeners;
class ExampleEventSubscriber
{
    /**
     * Handle user login events.
     */
    public function sendEmailNotification($event) {
        // get logged in username
        $email = $event->user->email;
        $username = $event->user->name;
        
        // send email notification about login...
    }
    /**
     * Handle user logout events.
     */
    public function warmUpCache($event) {
        if (isset($event->cache_keys) && count($event->cache_keys)) {
            foreach ($event->cache_keys as $cache_key) {
                // generate cache for this key
                // warm_up_cache($cache_key)
            }
        }
    }
    /**
     * Register the listeners for the subscriber.
     *
     * @param  Illuminate\Events\Dispatcher  $events
     */
    public function subscribe($events)
    {
        $events->listen(
            'Illuminate\Auth\Events\Login',
            'App\Listeners\ExampleEventSubscriber@sendEmailNotification'
        );
        
        $events->listen(
            'App\Events\ClearCache',
            'App\Listeners\ExampleEventSubscriber@warmUpCache'
        );
    }
}

这是subscribe方法,负责注册侦听器。 subscribe方法的第一个参数是Illuminate\Events\Dispatcher类的实例,您可以使用该类使用listen方法将事件与侦听器绑定。

listen方法的第一个参数是您要侦听的事件,第二个参数是在引发该事件时将被调用的侦听器。

这样,您可以在订户类本身中定义多个事件和侦听器。

事件订阅者类别不会自动获取。 您需要在$subscriber属性下的EventServiceProvider.php类中注册它,如以下代码片段所示。

<?php
namespace App\Providers;
use Illuminate\Support\Facades\Event;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
    /**
     * The subscriber classes to register.
     *
     * @var array
     */
    protected $subscribe = [
        'App\Listeners\ExampleEventSubscriber',
    ];
    /**
     * Register any events for your application.
     *
     * @return void
     */
    public function boot()
    {
        parent::boot();
        //
    }
}

这就是事件订阅者类供您使用,因此,我们也已达到本文的结尾。

结论

今天,我们讨论了Laravel的一些激动人心的功能-事件和听众。 它们基于观察者设计模式,该模式允许您引发应用程序范围的事件,并允许其他模块侦听这些事件并做出相应的反应。

只是想了解Laravel的速度,还是想通过扩展来扩展您的知识,网站或应用程序? 您可以在Envato市场上学习各种东西。

欢迎使用下面的提要表达您的想法!

翻译自: https://code.tutsplus.com/tutorials/custom-events-in-laravel--cms-30331

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值