Laravel: Events
Bài đăng này đã không được cập nhật trong 6 năm
Introduction
Các Event (sự kiện) của Laravel cung cấp việc thực hiện observer 1 cách đơn giản. Cho phép bạn đăng ký và lắng nghe các event khác nhau xảy ra trong ứng dụng của bạn. Các class Event thường được lưu trữ trong thư mục app/Events
, trong khi listener của chúng được lưu trong app/Listeners
. Đừng lo lắng nếu bạn không tìm thấy những thư mục này trong app của bạn, vì chúng sẽ được tạo ra cho bạn khi bạn tạo các Event và Listener bằng các lệnh console của Artisan
.
Event phục vụ như một cách tuyệt vời để tách rời các khía cạnh khác nhau trong app của bạn, vì một Event đơn lẻ có thể có nhiều Listener mà không phụ thuộc lẫn nhau. Ví dụ: bạn có thể muốn gửi thông báo Slack cho user mỗi lần một đơn đặt hàng đã được giao. Thay vì nối mã xử lý lệnh của bạn với mã thông báo Slack của bạn, bạn chỉ cần thêm một Event OrderShipped
mà Listener có thể nhận và chuyển đổi thành một thông báo Slack.
Registering Events & Listeners
EventServiceProvider
có trong ứng dụng Laravel của bạn cung cấp một vị trí thuận tiện để đăng ký tất cả event listeners của ứng dụng của bạn. Thuộc tính listen
chứa một mảng của tất cả các event (keys) và các listeners của chúng (value). Tất nhiên, bạn có thể thêm nhiều event cho mảng này như yêu cầu của ứng dụng của bạn. Ví dụ: hãy thêm sự kiện OrderShipped
:
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
'App\Events\OrderShipped' => [
'App\Listeners\SendShipmentNotification',
],
];
Generating Events & Listeners
Tất nhiên, thủ công tạo ra các file cho mỗi event và listener là rườm rà. Thay vào đó, chỉ cần thêm listener và event vào EventServiceProvider
của bạn và sử dụng lệnh event: generate
. Lệnh này sẽ tạo ra bất kỳ event hoặc listener nào được liệt kê trong EventServiceProvider
của bạn. Tất nhiên, các event và listener đã tồn tại sẽ không bị ảnh hưởng:
php artisan event:generate
Manually Registering Events
Thông thường, các event cần được đăng ký qua EventServiceProvider
$listen
array. Tuy nhiên, bạn cũng có thể đăng ký các Closure based event theo cách thủ công trong method boot
của EventServiceProvider
của bạn:
/**
* Register any other events for your application.
*
* @return void
*/
public function boot()
{
parent::boot();
Event::listen('event.name', function ($foo, $bar) {
//
});
}
Wildcard Event Listeners
Bạn thậm chí có thể đăng ký listener bằng cách sử dụng *
như một tham số ký tự đại diện, cho phép bạn nắm bắt nhiều event trên cùng một listener. Wildcard listener nhận tên event làm đối số đầu tiên và toàn bộ mảng dữ liệu event là đối số thứ hai của nó:
Event::listen('event.*', function ($eventName, array $data) {
//
});
Defining Events
một class Event chỉ đơn giản là một bộ chứa dữ liệu chứa thông tin liên quan đến event. Ví dụ: giả sử event OrderShipped
đã tạo của chúng ta nhận được một đối tượng Eloquent ORM
:
<?php
namespace App\Events;
use App\Order;
use Illuminate\Queue\SerializesModels;
class OrderShipped
{
use SerializesModels;
public $order;
/**
* Create a new event instance.
*
* @param Order $order
* @return void
*/
public function __construct(Order $order)
{
$this->order = $order;
}
}
Như bạn thấy, class event này không chứa logic. Nó chỉ đơn giản là một container cho trường hợp Order
đã được mua. Thuộc tính SerializesModels
trait được sử dụng bởi event này sẽ khéo léo sắp xếp theo thứ tự bất kỳ Eloquent model nếu đối tượng event được nối tiếp bằng cách sử dụng funtion serialize
của PHP.
Defining Listeners
Tiếp theo, chúng ta hãy nhìn vào listener cho event ví dụ của chúng ta. Event listeners nhận instance event trong phương thứchandle
của nó. câu lệnh event:generate
sẽ tự động nhập đúng class event và type-hint event trên phương thức handle
. Với phương thức handle
, bạn có thể thực hiện bất kỳ action cần thiết để đáp ứng event:
<?php
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...
}
}
Queued Event Listeners
Hàng đợi listener có thể có lợi nếu listener của bạn sẽ thực hiện một tác vụ chậm như gửi e-mail hoặc yêu cầu HTTP. Trước khi bắt đầu với queued listener, hãy chắc chắn configure your queue và start queue listener trên server hoặc môi trường phát triển local của bạn.
Để xác định rằng một listener nên được xếp hàng đợi, thêm interface ShouldQueue
vào class listener. Listener được tạo ra bởi lệnh Artisan event:generate
đã có interface này trên namespace hiện tại, do đó bạn có thể sử dụng nó ngay lập tức:
<?php
namespace App\Listeners;
use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendShipmentNotification implements ShouldQueue
{
//
}
Bây giờ, khi listener này được gọi cho một event, nó sẽ tự động xếp hàng bởi event dispatcher bằng queue system của Laravel. Nếu không có ngoại lệ nào được ném ra khi listener được thực hiện bởi hàng đợi, công việc được xếp hàng sẽ tự động bị xóa sau khi đã hoàn tất quá trình xử lý.
Customizing The Queue Connection & Queue Name
Nếu bạn muốn tùy chỉnh queue connection và queue name được sử dụng bởi một event listener, bạn có thể định nghĩa $connection
và $queue
trên listener class của bạn:
<?php
namespace App\Listeners;
use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendShipmentNotification implements ShouldQueue
{
/**
* The name of the connection the job should be sent to.
*
* @var string|null
*/
public $connection = 'sqs';
/**
* The name of the queue the job should be sent to.
*
* @var string|null
*/
public $queue = 'listeners';
}
Manually Accessing The Queue
Nếu bạn cần truy cập theo cách thủ công các phương thức delete
và realse
, bạn có thể thực hiện bằng cách sử dụng Illuminate\Queue\InteractsWithQueue
trait. Trait này được import mặc định trên listener được tạo và cung cấp quyền truy cập vào các phương thức sau:
<?php
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);
}
}
}
Handling Failed Jobs
Đôi khi queued event listener của bạn có thể không thành công. Nếu queued listener vượt quá số lần cố gắng tối đa được xác định bởi queue worker của bạn, phương thức failed
sẽ được gọi vào listener của bạn. Phương thức failed
nhận được thể hiện của event và exception gây ra sự cố:
<?php
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)
{
//
}
}
Dispatching Events
Để gửi một event, bạn có thể vượt qua một thể hiện của event đến event
helper. Helper sẽ gửi event tới tất cả listener đã đăng ký của mình. Vì event
helper là toàn cục, bạn có thể gọi nó từ mọi nơi trong ứng dụng của bạn:
<?php
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 Subscribers
Writing Event Subscribers
Event subscriber là các class có thể đăng ký nhiều event từ bên trong class, cho phép bạn xác định một số event handler trong một single class. Subscriber nên định nghĩa phương thức subscribe
, sẽ được thông qua một thể hiện của event dispatcher. Bạn có thể gọi phương thức listen
trên dispatcher đã cho để đăng ký event listener:
<?php
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'
);
}
}
Registering Event Subscribers
Sau khi viết subscriber, bạn đã sẵn sàng để đăng ký với event dispatcher. Bạn có thể đăng ký subscribers sử dụng $subscribe
property trên EventServiceProvider
. Ví dụ, hãy thêm UserEventSubScber
vào danh sách:
<?php
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',
];
}
All rights reserved