X

Laravel: Events

Giới thiệu về Laravel: Events

Tìm hiểu về Events trong laravel cùng LP xem qua 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.

Tìm hiểu về 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',
    ],
];

Tìm hiểu về 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

Tìm hiểu về 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) {
        //
    });
}

Tìm hiểu về 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) {
    //
});

Tìm hiểu về 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.

Tìm hiểu về 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 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 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$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 deleterealse , 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\'
        );

        $events->listen(
            'Illuminate\Auth\Events\Logout',
            'App\Listeners\'
        );
    }

}

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',
    ];
}