0
0
Lập trình
Admin Team
Admin Teamtechmely

Sử Dụng Sự Kiện Trong Laravel Để Tối Ưu Quy Trình

Đăng vào 1 tuần trước

• 6 phút đọc

Giới Thiệu

Khi xây dựng các ứng dụng Laravel, bạn có thể gặp phải tình huống mà một quy trình duy nhất yêu cầu xử lý nhiều tác vụ. Ban đầu, tôi đã viết tất cả trong các lớp dịch vụ, nhưng chúng nhanh chóng trở nên quá dài và lộn xộn. Mọi thứ trở thành một giao dịch lớn, và việc kiểm tra trở nên khó khăn vì tất cả logic được gói gọn trong một chỗ. Đó là lúc tôi nhận ra mình cần một cách tiếp cận tốt hơn. Tôi bắt đầu chia các phương thức thành các lớp riêng biệt. Phương pháp này tốt hơn nhiều, nhưng khi tham khảo tài liệu Laravel, tôi tìm thấy một giải pháp tốt hơn: sử dụng sự kiện. Nếu được sử dụng hiệu quả, mã của chúng ta sẽ trở nên sạch sẽ, dễ bảo trì và dễ kiểm tra hơn.

Sự Kiện Trong Laravel

Khi bạn cần thực hiện một loạt hành động để hoàn thành một quy trình, Sự kiện Laravel là công cụ phù hợp. Một sự kiện có thể kích hoạt nhiều listener, và mỗi listener là một lớp độc lập không phụ thuộc vào các listener khác. Điều này giữ cho quy trình làm việc mượt mà, tách rời và dễ mở rộng. Thay vì nhồi nhét mọi thứ vào một lớp dịch vụ cồng kềnh, bạn có thể chia nhỏ các tác vụ thành các đơn vị có thể kiểm tra riêng biệt, có thể thêm, xóa hoặc sửa đổi mà không làm ảnh hưởng đến phần còn lại. Bằng cách sử dụng sự kiện một cách hiệu quả, mỗi phần của quy trình của bạn vẫn sạch sẽ, tách biệt và dễ quản lý hơn khi ứng dụng của bạn phát triển.

Ví Dụ: E-Commerce – Khởi Tạo Cửa Hàng

Giả sử bạn đang xây dựng một nền tảng SaaS thương mại điện tử. Một người dùng đăng ký và tạo cửa hàng của họ.

Khi người dùng nhấn nút Lưu, các tác vụ sau sẽ diễn ra:

  1. Lưu cửa hàng.
  2. Gán cửa hàng cho người dùng đang xác thực.
  3. Gán vai trò admin cho người dùng.
  4. Gán quyền mặc định cho admin.
  5. Tạo các thương hiệu, danh mục và sản phẩm mặc định.
  6. Gửi email cho admin thông báo: "Cửa hàng của bạn đã sẵn sàng."
  7. Gửi email cho super admin thông báo "Một cửa hàng mới đã được đăng ký".

Hãy nghĩ xem:

Bạn có nên đặt tất cả vào controller? Trong một service? Trong một job?

Không. Chỉ cần kích hoạt một sự kiện:

php Copy
event(new StoreCreated($store));

Điều này sẽ kích hoạt tất cả các hành động cần thiết để hoàn thành quy trình này. Đây là cách chúng ta thực hiện.

bash Copy
php artisan make:event StoreCreated

Điều này sẽ tạo ra lớp sau trong thư mục app/Events:

php Copy
<?php

namespace App\Events;

use App\Models\Store;
use Illuminate\Foundation\Events\Dispatchable;

class StoreCreated
{
    use Dispatchable;

    /**
     * Tạo một phiên bản sự kiện mới.
     */
    public function __construct(
        public Store $store,
    ) {}
}

Tiếp theo, chúng ta cần tạo các listener cho sự kiện này.

bash Copy
php artisan make:listener AssignStore --event=StoreCreated
php artisan make:listener AssignAdminRole --event=StoreCreated
php artisan make:listener AssignAdminAbilities --event=StoreCreated
php artisan make:listener AddDefaultBrands --event=StoreCreated
php artisan make:listener AddDefaultCategories --event=StoreCreated
php artisan make:listener AddDefaultProducts --event=StoreCreated
php artisan make:listener SendStoreReadyEmail --event=StoreCreated
php artisan make:listener SendNewStoreCreatedEmail --event=StoreCreated

Đăng Ký Listener: Cách Mới

Nếu chúng ta tạo một listener, Laravel sẽ tự động quét thư mục Listeners và đăng ký nó cho chúng ta. Khi chúng ta định nghĩa một phương thức listener như handle và chỉ định sự kiện trong chữ ký của nó, Laravel biết sự kiện nào mà nó nên phản hồi. Ví dụ, nếu bạn chạy:

bash Copy
php artisan make:listener AssignStore --event=StoreCreated

Laravel sẽ tạo listener và liên kết nó với sự kiện StoreCreated tự động.

Lưu ý: Bạn cũng có thể tạo thư mục trong thư mục listeners để nhóm tất cả các listener cần được xử lý cùng nhau. Ví dụ, để giữ cho đơn giản, hãy sử dụng cùng tên với sự kiện để tạo một thư mục.

plaintext Copy
app/
└── Listeners/
    └── StoreCreated/
        └── AssignStore.php
        └── AssignAdminRole.php
        └── AssignAdminAbilities.php
        └── AddDefaultBrands.php           
        └── AddDefaultCategories.php
        └── AddDefaultProducts.php
        └── SendStoreReadyEmail.php           
        └── SendNewStoreCreatedEmail.php

Và lệnh của chúng ta sẽ như sau:

bash Copy
php artisan make:listener StoreCreated/AssignStore --event=StoreCreated

Tùy Chỉnh Của Tôi

Nếu bạn muốn giữ cách cũ (như tôi), bạn có thể làm như sau:

bash Copy
php artisan make:provider EventServiceProvider

Điều này sẽ tạo ra lớp EventServiceProvider trong thư mục app/Providers:

php Copy
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class EventServiceProvider extends ServiceProvider
{
    /**
     * Đăng ký dịch vụ.
     */
    public function register(): void
    {
        //
    }

    /**
     * Khởi động dịch vụ.
     */
    public function boot(): void
    {
        //
    }
}

Bây giờ chúng ta có thể tạo thuộc tính $listen và thực hiện các tác vụ.

php Copy
protected $listen = [

    StoreCreated::class => [
        AssignStore::class,
        AssignAdminRole::class,
        AssignAdminAbilities::class,
        AddDefaultBrands::class,
        AddDefaultCategories::class,
        AddDefaultProducts::class,
        SendStoreReadyEmail::class,
        SendNewStoreCreatedEmail::class,
    ],
]; 

Nếu bạn làm điều này, bạn có thể đặt các lớp của mình ở bất kỳ đâu trong ứng dụng, như services, helpers hoặc AQC. Chỉ cần định nghĩa phương thức handle() và chỉ định sự kiện lớp vào đó.

Cuối cùng, chúng ta có thể gọi sự kiện sau khi đã lưu dữ liệu cửa hàng. Tôi thường thích làm điều này trong lớp Observer.

php Copy
<?php

namespace App\Observers;

use App\Models\Store;
use App\Events\StoreCreated;

class StoreObserver
{
    public function created(Store $store)
    {  
        event(new StoreCreated($store));     
    }
}

Những Suy Nghĩ Cuối Cùng

Khi xây dựng các ứng dụng Laravel có khả năng mở rộng, rất dễ để rơi vào bẫy nhồi nhét các controller hoặc lớp dịch vụ với quá nhiều trách nhiệm. Các sự kiện và listener cung cấp một cách sạch sẽ và thanh lịch để tách biệt các mối quan tâm trong khi vẫn giữ cho mã của bạn linh hoạt. Bằng cách chia nhỏ các quy trình thành các listener độc lập, bạn có được khả năng kiểm tra, bảo trì và khả năng mở rộng quy trình mà không sợ làm hỏng logic hiện có. Dù bạn giữ lại việc phát hiện sự kiện tự động của Laravel hay thích cách lập bản đồ EventServiceProvider cũ, điều quan trọng là tính nhất quán. Khi bạn bắt đầu áp dụng các sự kiện, bạn sẽ thấy mã của mình tự nhiên tiến hóa thành một hệ thống dễ hiểu hơn, dễ kiểm tra hơn và linh hoạt hơn với các yêu cầu trong tương lai.


Nếu bạn thấy bài viết này hữu ích, hãy xem xét việc hỗ trợ công việc của tôi — điều đó có ý nghĩa rất lớn với tôi.

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào