laravel笔记-事件
写在前面
时间可贵,善用目录↑
学习Laravel的笔记,仅仅是作为laravel文档笔记,目的是强化对文档的理解,质量不高。
什么是事件
Laravel事件提供了简单的观察者模式实现,允许你订阅和监听应用中的事件。事件类通常存放在 app/Events 目录,监听器存放在app/Listeners。如果你在应用中没有看到这些目录,不要担心,因为它们会在你使用Artisan命令生成事件和监听器的时候创建。
事件的使用
注册
在自带的EventServiceProvider中注册事件,其中的listen属性包含了事件(键)和对应的监听器(值)。
比如我们先注册一个OrderShipped 事件:
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
//这是事件
'App\Events\OrderShipped' => [
//对应的监听器
'App\Listeners\SendShipmentNotification',
],
];
当然,作为服务提供者,我们也可以手动通过EventServiceProvider中的boot函数绑定。
/**
* Register any other events for your application.
*
* @return void
*/
public function boot()
{
parent::boot();
Event::listen('event.name', function ($foo, $bar) {
//
});
}
生成
默认情况下事件在 app/Events 目录下,监听器在app/Listeners目录下。
手动生成事件和监听器是很笨重的,所以我们可以通过Artisan命令自动生成事件和监听器。当然生成的前提是你先在EventServiceProvider中注册事件/监听器。
比如经过上面的操作后我执行:
php artisan event:generate
定义
事件
事件类是一个处理与事件相关的简单数据容器,例如,假设我们生成的 OrderShipped 事件接收一个Eloquent ORM对象:
namespace App\Events;
use App\Order;
use App\Events\Event;
use Illuminate\Queue\SerializesModels;
class OrderShipped extends Event
{
use SerializesModels;
public $order;
/**
* Create a new event instance.
*
* @param Order $order
* @return void
*/
public function __construct(Order $order)
{
$this->order = $order;
}
}
该事件类不包含任何特定逻辑,只是一个存放被购买的 Order 对象的容器,如果事件对象被序列化的话,事件使用的 SerializesModels trait 将会使用 PHP 的 serialize 函数序列化所有 Eloquent 模型。
监听器
事件监听器在 handle 方法中接收事件实例.
namespace App\Listeners;
use App\Events\OrderShipped;
class SendShipmentNotification
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param OrderShipped $event
* @return void
*/
public function handle(OrderShipped $event)
{
// Access the order using $event->order...
}
}
如果需要停止事件继续往下传播:可以在handle方法中返回false。
分发
当我们需要触发事件的时候,可以传递事件实例到辅助函数event。
这个辅助函数会分发事件到所有注册的监听器。由于辅助函数 event 全局有效,所以可以在应用的任何地方调用它。
也可以使用Event::fire()来分发。
namespace App\Http\Controllers;
use App\Order;
use App\Events\OrderShipped;
use App\Http\Controllers\Controller;
class OrderController extends Controller
{
/**
* Ship the given order.
*
* @param int $orderId
* @return Response
*/
public function ship($orderId)
{
$order = Order::findOrFail($orderId);
// Order shipment logic...
event(new OrderShipped($order));
//Event::fire(new OrderShipped($order));
}
}
事件监听器队列
如果监听器将要执行耗时任务比如发送邮件或者发送HTTP请求,可以将监听器放到队列中。
只需要让监听器类实现 ShouldQueue 接口即可 将监听器放入列队:
namespace App\Listeners;
use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendShipmentNotification implements ShouldQueue
{
//
}
手动访问队列
如果需要手动访问列队的delete和release方法可以使用监听器默认导入的Illuminate\Queue\InteractsWithQueue trait 。
namespace App\Listeners;
use App\Events\OrderShipped;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendShipmentNotification implements ShouldQueue
{
use InteractsWithQueue;
public function handle(OrderShipped $event)
{
if (true) {
$this->release(30);
}
}
}
处理失败任务
有时候队列中的事件监听器可能会执行失败。如果队列中的监听器任务执行时超出了队列进程定义的最大尝试次数,监听器上的failed方法会被调用,failed方法接收事件实例和造成失败的异常。
namespace App\Listeners;
use App\Events\OrderShipped;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendShipmentNotification implements ShouldQueue
{
use InteractsWithQueue;
public function handle(OrderShipped $event)
{
//
}
public function failed(OrderShipped $event, $exception)
{
//这里是失败的操作
}
}
事件订阅者
事件订阅者是指那些在类本身中订阅多个事件的类,通过事件订阅者你可以在单个类中定义多个事件处理器。
我个人理解,事件订阅者就是一个有很多处理方法的监听者。
普通监听者中只有handle方法可以处理时间。
但是在事件订阅者中可以定义多个方法,然后在subscribe方法中注册事件。然后根据不同的情况使用对应的方法分别处理。
定义一个订阅者:
namespace App\Listeners;
class UserEventSubscriber
{
/**
* Handle user login events.
*/
public function onUserLogin($event) {}
/**
* Handle user logout events.
*/
public function onUserLogout($event) {}
/**
* Register the listeners for the subscriber.
*
* @param Illuminate\Events\Dispatcher $events
*/
public function subscribe($events)
{
$events->listen(
'Illuminate\Auth\Events\Login',
'App\Listeners\UserEventSubscriber@onUserLogin'
);
$events->listen(
'Illuminate\Auth\Events\Logout',
'App\Listeners\UserEventSubscriber@onUserLogout'
);
}
}
注册订阅者,在subscribe属性中:
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
//
];
/**
* The subscriber classes to register.
*
* @var array
*/
protected $subscribe = [
'App\Listeners\UserEventSubscriber',
];
}