Laravel Event là gì?
Một sự kiện trong máy tính là hành động hay một cái gì đó xảy ra tại một thời điểm xác định bởi một chương trình máy tính và có thể quản lý bằng các chương trình máy tính. Một vài ví dụ về sự kiện trong Laravel:
- Một người dùng đăng ký mới.
- Một bài viết được đăng.
- Một thành viên viết lời bình luận.
- Người dùng like một bức ảnh.
Tại sao sử dụng Laravel Event?
Có một số lý do cơ bản làm chúng ta thấy được Laravel Event có ý nghĩa như thế nào:
- Laravel Event giúp chúng ta tách biệt các thành phần trong ứng dụng, khi một sự kiện xảy ra, sự kiện không cần biết những gì khác ngoài việc thực thi công việc của nó.
- Không có Laravel Event sẽ phải đặt rất nhiều các code logic ở một chỗ.
- Một lý do nữa khi sử dụng Laravel Event đó là tăng tốc độ trong xử lý dữ liệu ứng dụng. Ví dụ, một bài viết mới được đăng sẽ gửi mail đến tất cả các thành viên, việc gửi mail đến hàng triệu thành viên sẽ mất khá nhiều thời gian, với Laravel event gửi email sẽ là một trigger khi một bài viết mới được tạo ra. Với cách viết code cũ trước đây, tất cả xử lý đưa vào tính năng đăng bài mới khiến việc đăng một bài mất rất nhiều thời gian. Một ví dụ khác, khi thanh toán đơn hàng, phải gửi email thông báo đến khách hàng, việc thanh toán đơn hàng là ưu tiên nhất và cần thời gian xử lý cực nhanh đảm bảo trải nghiệm tốt cho khách hàng, nếu email khách hàng nhận hiện đang có vấn đề, xử lý gửi mail sẽ vào một vòng lặp thử liên tục gửi, như vậy việc thanh toán sẽ rất lâu. Với Laravel Event mọi việc được tách biệt rất rõ và tăng tốc trong xử lý dữ liệu ứng dụng.
Bắt đầu với Laravel Event
Chúng ta đã dần hiểu Laravel Event là gì và lợi ích của nó, tiếp theo chúng ta sẽ đi vào tìm hiểu xem Laravel Event hoạt động như thế nào?
Laravel Event cho phép bạn đăng ký sự kiện và tạo các listener cho rất nhiều các sự kiện xảy ra trong ứng dụng. Các class Event được lưu trữ trong app/Events và các listener được lưu trong app/Listeners. Nếu bạn không thấy hai thư mục này trong project cũng đừng lo vì các câu lệnh artisan tạo các event, listerner sẽ tự động tạo ra chúng. Một event có thể có rất nhiều listerner được tạo ra và các listener này độc lập với nhau. Chúng ta sẽ xem các bước tạo, đăng ký và sử dụng Event, Listerner trong Laravel.
Bước 1: Định nghĩa Event
Event được tạo ra đơn giản bằng cách sử dụng câu lệnh artisan:
php artisan make:event OrderPayment
nó sẽ tạo ra một class Event nằm trong app\Events như sau:
<?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 OrderPayment
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Get the channels the event should broadcast on.
*
* @return Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel(\'channel-name\');
}
}
php artisan make:event OrderPayment
<?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 OrderPayment
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Get the channels the event should broadcast on.
*
* @return Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel(\'channel-name\');
}
}
Bước 2: Tạo Event Listener
Ngay khi một event xảy ra, ứng dụng cần biết để thực hiện các việc khác, đó chính là lý do cần Event Listerner. Để tạo Listerner đơn giản là sử dung lệnh artisan:
c:\xampp\htdocs\laravel-test>php artisan make:listener SendEmailAfterOrderPayment --event="OrderPayment"
Listener created successfully.
Khi đó, sẽ tạo ra class SendEmailAfterOrderPayment.php trong app\Listerners với nội dung:
<?php
namespace App\Listeners;
use App\Events\OrderPayment;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendEmailAfterOrderPayment
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param OrderPayment $event
* @return void
*/
public function handle(OrderPayment $event)
{
//
}
}
Phương thức handle() với tham số đầu vào là một instance của Event mà Listener được gán vào, phương thức này sẽ được dùng để thực hiện các công việc cần thiết để đáp lại Event. Instance đầu vào của phương thức cũng chứa cả các giá trị mà Event truyền sang. Ví dụ:
/**
* Handle the event.
*
* @param OrderPayment $event
* @return void
*/
public function handle(OrderPayment $event)
{
//
$order_amout = $event->order->amount;
...
}
Đôi khi bạn muốn dừng quảng bá Event này đến các Listener khác, rất đơn giản bạn trả về giá trị false trong phương thức handle() của Listerner đang xử lý.
c:\xampp\htdocs\laravel-test>php artisan make:listener SendEmailAfterOrderPayment --event="OrderPayment"
Listener created successfully.
<?php
namespace App\Listeners;
use App\Events\OrderPayment;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendEmailAfterOrderPayment
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param OrderPayment $event
* @return void
*/
public function handle(OrderPayment $event)
{
//
}
}
/**
* Handle the event.
*
* @param OrderPayment $event
* @return void
*/
public function handle(OrderPayment $event)
{
//
$order_amout = $event->order->amount;
...
}
Bước 3: Đăng ký Event
Trước khi đến các bước xử lý trong Event, chúng ta cần đăng ký Event, mở file app/Providers/EventServiceProvider.php và tìm đến thuộc tính $listener.
protected $listen = [
\'App\Events\OrderPayment\' => [
\'App\Listeners\SendEmailAfterOrderPayment\',
],
];
Chúng ta đã khai báo Listerner này của Event nào, một Event có thể có nhiều các Listener khác nhau:
protected $listen = [
\'App\Events\OrderPayment\' => [
\'App\Listeners\SendEmailAfterOrderPayment\',
\'App\Listeners\SendSMSAfterOrderPayment\',
],
];
Ba bước trên có thể được thực hiện đơn giản hơn bằng cách gán Listener cho Event trong file app/Providers/EventServiceProvider.php sau đó chạy lệnh:
c:\xampp\htdocs\laravel-test>php artisan event:generate
Events and listeners generated successfully!
Khi đó, các class trong app\Events và app\Listeners sẽ được tự động sinh ra.
protected $listen = [
\'App\Events\OrderPayment\' => [
\'App\Listeners\SendEmailAfterOrderPayment\',
],
];
protected $listen = [
\'App\Events\OrderPayment\' => [
\'App\Listeners\SendEmailAfterOrderPayment\',
\'App\Listeners\SendSMSAfterOrderPayment\',
],
];
c:\xampp\htdocs\laravel-test>php artisan event:generate
Events and listeners generated successfully!
Bước 4: Tạo ra thông báo sự kiện xảy ra
Khi thực hiện một đoạn code nào đó, muốn thông báo đến hệ thống là sự kiện xảy ra để các listener có thể biết được chúng ta sử dụng phương thức fire().
use Event;
use App\Events\OrderPayment;
// Các xử lý thanh toán đơn hàng ở đây
$order = new Order;
$order->amount = 2000000;
$order->note = \'Tạo đơn hàng mẫu\';
...
$order->save();
// Phần xử lý thanh toán xong, tạo ra thông báo sự kiện xảy ra cho các Listener biết
event(new OrderPayment($order));
Hoặc cũng có thể dùng helper method event để tạo ra thông báo
use App\Events\OrderPayment;
// Các xử lý thanh toán đơn hàng ở đây
...
// Phần xử lý thanh toán xong, tạo ra thông báo sự kiện xảy ra cho các Listener biết
event(new OrderPayment($order));
Đối tượng $order sẽ được truyền sang Listener.
use Event;
use App\Events\OrderPayment;
// Các xử lý thanh toán đơn hàng ở đây
$order = new Order;
$order->amount = 2000000;
$order->note = \'Tạo đơn hàng mẫu\';
...
$order->save();
// Phần xử lý thanh toán xong, tạo ra thông báo sự kiện xảy ra cho các Listener biết
event(new OrderPayment($order));
use App\Events\OrderPayment;
// Các xử lý thanh toán đơn hàng ở đây
...
// Phần xử lý thanh toán xong, tạo ra thông báo sự kiện xảy ra cho các Listener biết
event(new OrderPayment($order));
Bước 5 (Tùy chọn): Đưa Event Listener vào hàng đợi
Đôi khi bạn không muốn các event và listener làm ảnh hưởng đến hoạt động của ứng dụng, ví dụ khi người dùng thanh toán đơn hàng không phải chờ đợi thời gian email về thanh toán gửi tới địa chỉ mail người dùng, bạn có thể đưa event listener vào hàng đợi và nó sẽ được quản lý bởi queue driver do bạn xác định. Để làm điều này rất đơn giản là implement Illuminate\Contracts\Queue\ShouldQueue.
<?php
namespace App\Listeners;
use App\Events\OrderPayment;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendEmailAfterOrderPayment implements ShouldQueue
{
//
}
Khi đó, khi Listener được gọi bởi một Event, nó sẽ tự động được đưa vào hàng đợi bởi hệ thống hàng đợi của Laravel. Nếu không có exception nào xảy ra, queue job sẽ tự động được xóa sau khi nó hoàn thành xử lý.
Laravel còn cho phép truy xuất các Listener trong queue job một cách thủ công bằng các phương thức như delete(), handle(), chú ý phải sử dụng trail Illuminate\Queue\InteractsWithQueue. Đôi khi các job trong hàng đợi cũng có thể gặp lỗi, để xử lý chúng dùng phương thức failed().
<?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);
}
}
public function failed(OrderShipped $event, $exception)
{
//
}
}
<?php
namespace App\Listeners;
use App\Events\OrderPayment;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendEmailAfterOrderPayment implements ShouldQueue
{
//
}
<?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);
}
}
public function failed(OrderShipped $event, $exception)
{
//
}
}

Nhận xét
Đăng nhận xét