Tìm hiểu Event trong Laravel – Blog Văn Long

1. Event là gì ?

Event là sự kiện, là một hành đông hay một tác vụ nào đó xả ra ở một thời điểm xác định. Trong những hệ thống web của chúng ta cũng có rất nhiều sự kiện xảy ra. Ví dụ như sự kiện một sản phẩm mới vừa được tạo, hay sự kiện khi chúng ta nhấn vào một button nào đỏ, hay đổi khi trên Facebook chúng ta cũng có những nut like, dislike cũng là một sự kiện…vv. Đôi khi chúng ta cần xử lý những sự kiện này hay nói một cách khác đó chính là cần một phản hồi lại cho user khi kích hoạt một sự kiện nào đó trong hệ thống của chúng ta. Để làm được điều này thì thật may mắn Laravel cũng cấp cho chúng ta cái gọi là Event. Để dễ hiểu hơn một chút thì trong bài viết này mình sẽ đưa ra một ví dụ thực tế cụ thể đó chính là khi một chương trình quảng cáo được tạo ra thì chúng ta se gửi mail cho người dùng hệ thống.

2. Ví dụ cụ thể

2.1 Đặt vấn đề

Bài toán của tất cả chúng ta đưa ra là gửi mail cho tổng thể người dùng mạng lưới hệ thống khi có một chương trình quảng cáo được tạo ra .

Thực thi bài toán

Giả sử bảng discounts của tất cả chúng ta chỉ có những trường sau : id, title, content, created_at, updated_at cho nó đơn thuần nhé. Sau đó những bạn tạo Mã Sản Phẩm, migration

Tạo Event và Listener

Tiếp theo chúng ta sẽ tạo event và listener nhé, folder chứa sự kiện là app\Events, folder chứa listener là app\Listeners. Nhưng ban đầu khi init project Laravel thì các bạn sẽ không thấy đâu, chúng ta có thể tự tạo hoặc sử dụng hỗ trợ command line Artisan. Chúng ta có 2 cách để tạo sự kiện và listener bằng command line

php artisan make:event DiscountEvent
// và chúng ta tạo listerner tương ứng cho sự kiện này
php artisan make:listener SendEmailDiscountEvent –event=”DiscountEvent”
//sau khi tạo ra event là listener ở trên chúng ta phải vào app/Providers/EventServiceProvider.php để khai báo

12345

protectedUSDlisten=[

‘ App \ Events \ DiscountEvent ‘=>[

‘ App \ Listeners \ SendEmailDiscountEvent ‘

],

];

hoặc là chúng ta sẽ khai báo trước trong app/Providers/EventServiceProvider.php như trên và sau đó sử dụng câu lệnh sau để generate ra event và listener

php artisan event : generate

Mình thì hay dùng cách thứ 2 hơn vì nó nhanh gọn ????

Cách định nghĩa Event và Listener

12345678910111213141516171819202122232425

namespaceApp\Events;

useIlluminate\Broadcasting\Channel;

useIlluminate\Queue\SerializesModels;

useIlluminate\Broadcasting\PrivateChannel;

useIlluminate\Broadcasting\PresenceChannel;

useIlluminate\Foundation\Events\Dispatchable;

useIlluminate\Broadcasting\InteractsWithSockets;

useIlluminate\Contracts\Broadcasting\ShouldBroadcast;

useApp\Discount;

classSendEmailUser

{

useDispatchable,InteractsWithSockets,SerializesModels;

publicUSDdiscount;

/ * *

* Create a new event instance .

*

* @ return void

* /

publicfunction__construct(DiscountUSDdiscount)

{

USDthis->discount=USDdiscount;

}

}

Như chúng ta thấy event này của chúng ta không chứa bất cứ logic nào. Nó đơn giản là một container cho đối tượng Discount.

Tiếp theo khi sự kiện đã được kích hoạt thì chúng ta cần một phản hồi lại cho sự kiện, lúc đó Listener sẽ đảm nhận nhiệm vu này

12345678910111213141516171819202122232425262728

namespaceApp\Listeners;

useApp\Events\DiscountEvent;

useIlluminate\Queue\InteractsWithQueue;

useIlluminate\Contracts\Queue\ShouldQueue;

classListenerSendEmailEvent

{

/ * *

* Create the event listener .

*

* @ return void

* /

publicfunction__construct()

{

/ /

}

/ * *

* Handle the event .

*

* @ param Discount $ event

* @ return void

* /

publicfunctionhandle(DiscountEventUSDevent)

{

/ /

}

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 để phản hồi hay đáp lại Event mà nó theo dõi. Instance đầu vào của phương thức này cũng chứa cá các giá trị mà Event truyền sang. Ví dụ ta sẽ xử lý sự kiện mà mình đã nếu trong bài toán của chúng ta như sau:

12345678

public

function

handle(DiscountEventUSDevent)

{

USDusers=User::all();

foreach(USDusersasUSDuser){

Mail::to(USDuser->email)

->send(newSendEmailUser(USDevent->discount));

}

}

Trong phương thức hanlde() trên nếu bạn muốn ngừng cái hồi đáp từ listener cho event thì bạn có thể return false để dừng ngay những phản hồi đó.  1  vấn đề ở đây là nếu gửi mail cho tất cả các thành viên khi ấn submit bài post thì sẽ cực kỳ lâu. Các bạn có thể tìm hiểu BackgroudJob, trong Laravel nó là Queue. Các bạn có thể xếp event listener vào hàng đợi để quá trình khi submit bài post không bị chờ đợi load quá lâu.

2.2.3. Queue

Việc gửi mail cho tất cả người dùng trong hệ thống là khá tốn thời gian. Thay vì khi submit một chương trình discount phải chờ đợi cho nó load hết để gửi hết mail cho mọi người thì chúng ta có thể gác việc gửi mail sang một bên bằng cách đưa việc gửi mail vào hàng đợi và gửi dần sau đó. Để áp dụng Queue cho listener ta chỉ cần implement interface ShouldQueue vào listener

12345

useIlluminate\Contracts\Queue\ShouldQueue;

classSendMailDiscountEventimplementsShouldQueue

{

/ / …

}

2.2.3.Kích hoạt Event.

Có rất nhiều cách để kích hoạt Event trong Laravel, các bạn tham khảo một số cách sau nhé. Cách đầu tiên chúng ta sẽ sử dụng helper event.

1234567891011

publicfunctionstore(RequestUSDrequest)

{

USDdiscount=newDiscount();

USDdiscount->title=USDrequest->title;

USDdiscount->content=USDrequest->content;

USDdiscount->save();

event(newDiscountEvent(USDdiscount));

returnredirect()->route(‘ discounts ‘);

}

Cách thứ 2 chúng ta sẽ sử dụng Facade Event

1234567891011

publicfunctionstore(RequestUSDrequest)

{

USDdiscount=newDiscount();

USDdiscount->title=USDrequest->title;

USDdiscount->content=USDrequest->content;

USDdiscount->save();

Event::fire(‘ discount ‘,[‘ discount ‘=>USDdiscount]);

returnredirect()->route(‘ discounts ‘);

}

Xong rồi trong app / Providers / EventServiceProvider. php tất cả chúng ta cần ĐK listener nào sẽ Giao hàng sự kiện này .

123456

publicfunctionboot()

{

parent::boot();

Event::listen(‘ discount ‘,’ App \ Events \ DiscountEvent ‘);

}