12/08/2018, 16:59

Event trong Laravel

Mở đầu Event là sự kiện là một hành động hay một tác vụ nào đó xảy ra ở một thời điêm xác định.Trong đời thường cũng như trong quá trình hoạt động của một ứng dụng có rất nhiều event xảy ra. Ví dụ như trong ứng dụng web của chúng ta khi người dùng click lên một button là một sự kiện, khi người ...

Mở đầu

Event là sự kiện là một hành động hay một tác vụ nào đó xảy ra ở một thời điêm xác định.Trong đời thường cũng như trong quá trình hoạt động của một ứng dụng có rất nhiều event xảy ra. Ví dụ như trong ứng dụng web của chúng ta khi người dùng click lên một button là một sự kiện, khi người dùng thêm sản phẩm vào giỏ hàng là một sự kiện..v.v.. Đôi khi chúng ta cần xử lý các sự kiện này, và định nghĩa các tác vụ mà ứng dụng của chúng ta cần phản hồi lại khi một sự kiện xác định xảy ra. Để giúp chúng ta làm được việc này laravel cung cấp cho chúng ta cái gọi là Event. Để biết được cách sử dụng event trong laravel cụ thể ra sao. Mình xin đưa ra một trường hợp thực tế như sau đây..

Gửi mail xác nhận đơn hàng khi có sự kiện khách hàng Order sản phẩm

Đây là một trường hợp thực tế hay gặp nhất là khi chúng ta xây dựng ứng dụng web thương mại điện tử. Khi khách hàng đặt hàng, xem lại thông tin giỏ hàng và quyết định submit đơn hàng. Ứng dụng web của chúng ta sẽ gửi một email về thông tin chi tiết đơn hàng, tổng thanh toán và thông tin thanh toán thêm lần nữa vào email cho khách hàng xác nhận hoặc lưu trữ, đối chiếu thông tin đơn hàng khi cần thiết. Bây giờ mình xin hướng dẫn cách tạo event, lắng nghe event và gửi mail cho trường hợp đã mô trả trên đây.

Đăng ký event và listener

Laravel cung cấp cho chúng ta một cách thuận tiện để bạn có thể đăng ký event và listener cho event của bạn, bằng cách truy cập vào appProvidersEventServiceProvider trong file này bạn đăng ký event và listener tương ứng như sau :

 protected $listen = [
        'AppEventsCustomerOrder' => [
            'AppListenersSendMailConfirmOrder',
        ],
    ];

Trong đó:

  • customerOrder Là tên sự kiện khi người dùng đặt hàng
  • sendMailConfirmOrder là tên listener tương ứng với sự kiện customerOrder. Như bạn cũng có thể đoán được, ta sẽ lắng nghe sự kiện người dùng đặt hàng và khi nó xảy ra. Ta sẽ gửi một email xác nhận đơn hàng tới người dùng

Sinh class event và listener

Sau khi đăng ký như bước trên. Bạn chạy lệnh sau :

php artisan event:generate

Kiểm tra lại, có thể thấy lúc này trong project của chúng ta đã sinh thêm hai folder là Events và Listeners trong hai folder này chức hai file tương ứng là customerOrder.php và sendMailConfirmOrder.php

Định nghĩa sự kiện

Trong file customerOrder ta định nghĩa thêm thuộc tính và hàm construct như sau

<?php

namespace AppEvents;

use IlluminateBroadcastingChannel;
use IlluminateQueueSerializesModels;
use IlluminateBroadcastingPrivateChannel;
use IlluminateBroadcastingPresenceChannel;
use IlluminateFoundationEventsDispatchable;
use IlluminateBroadcastingInteractsWithSockets;
use IlluminateContractsBroadcastingShouldBroadcast;
use AppBills;
use AppCustomer;

class CustomerOrder
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    /**
     * Create a new event instance.
     *
     * @return void
     */

    public $bill;
    public function __construct(Bills $userBillInfor)
    {
        $this->bill = $userBillInfor;
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return Channel|array
     */
    public function broadcastOn()
    {
        return new PrivateChannel('channel-name');
    }
}


Ở đây tham số truyền vào hàm construct của event là một instance của model Bill ( Để ta lấy thông tin đơn hàng mà khách hàng vừa đặt )

Định nghĩa Listener

<?php

namespace AppListeners;

use AppEventscustomerOrder;
use IlluminateQueueInteractsWithQueue;
use IlluminateContractsQueueShouldQueue;
use Mail;
use AppMailSubmitOrderMail;

class SendMailConfirmOrder
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Handle the event.
     *
     * @param  customerOrder  $event
     * @return void
     */
    public function handle(customerOrder $event)
    {
        Mail::to($event->bill->customer->email)
        ->send(new SubmitOrderMail($event->bill->customer, $event->bill));
    }
}

public function handle() là phương thức chịu trách nhiệm xử lý tác vụ đáp lại một sự kiện khi nó xảy ra. Trong trường hợp này, khi người dùng nhấn submit order thì sự kiện sẽ được kích hoạt, listener sẽ lắng nghe và bắt lấy sự kiện này và gửi mail cho khách hàng... Còn việc gửi mail chi tiết như thế nào, thì đã có khá nhiều bài viết trên Viblo bạn có thể tham khảo một sô bài viết khác trên viblo ở đây, hay ở đây ...v..v Trong đoạn code trên, ta có thể truy cập đến biến bill mà ta đã khai báo khi định nghĩa event bằng cách truy cập $event->bill, như bạn có thể thấy ở trên.

Phát đi sự kiện

Bây giờ ta cần phát đi sự kiện. Từ nãy đến giờ là cúng ta ngầm hiểu khi khách hàng submit order là sự kiển xảy ra. Nhưng máy tính thì đâu tự động hiểu được chuyện đó. Chúng ta cần phải có đoạn code để máy tính biết được lúc nào thì nên phát ra sự kiện. Giả sử trong ứng dụng của chúng ta. Khi khách hàng xem xong giỏ hàng và quyết định đặt hàng. Một form sẽ được gửi lên server và được xử lý bằng controller tên là ProcessBillController và phương thức xử lý request vừa xong trong controller này là processSubmitOrder trong phương thức này ta phát đi sự kiện bằng cách

public function processSubmitOrder(Request $request){
    //...lưu thông tin vào đơn hàng..v..vv
    event(new customerOrder($bill));
}

event(new customerOrder($bill)); sẽ phát đi sự kiện customerOrder. Lúc này, Listener sendMailConfirmOrder sẽ đón nhận sự kiện trên và phản hồi bằng việc gửi đi một Email xác thực đơn hàng....

Xếp event listener vào hàng đợi

Việc này có thể hiểu là sau khi khách hàng nhấn đặt hàng. Thay vì để khách hàng đợi ứng dụng gửi mail xong mới phản hồi (Ứng dụng sẽ bị chậm) thì ta tạm thời gác việc gửi mail sang một bên và báo luôn đặt hàng thành công cho khách hàng. Còn việc gửi mail sẽ đưa 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 như dưới đây

use IlluminateContractsQueueShouldQueue;
class SendMailConfirmOrder 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ý.

Kết luận

Vừa xong mình vừa nêu được một số thao tác cơ bản khi làm việc với event trong laravel. Như tạo sự kiện, tạo listener, phát đi và lắng nghe sự kiện, xử lý khi nó xảy ra.... Trong ứng dụng chúng ta có rất nhiều trường hợp cần sử dụng event. Qua bài viết trên, hy vọng giúp ích cho một số bạn chưa biết cách sử dụng event trong laravel có thể biết thêm căn bản... Mong nhận được sự góp ý từ mọi người...

0