Pipeline Design Pattern là nơi mà các dữ liệu được chuyển qua một chuỗi các nhiệm vụ hoặc giai đoạn.

Pipeline hoạt động giống như một chuỗi dây chuyền lắp ráp, nơi dữ liệu được xử lý và sau đó, sẽ được chuyển sang giai đoạn tiếp theo.

Sử dụng Pipeline trong dự án sẽ là một điểm lợi thế, vì nó sẽ dễ dàng giúp chúng ta trong việc chuyển đổi một quy trình phức tạp ra thành các nhiệm vụ riêng rẻ.

Cũng như, nó cũng dễ dàng giúp chúng ta trong việc thêm, xóa hoặc thay thế một giai đoạn nào đó trong Pipeline mà không làm ảnh hưởng đến toàn bộ quá trình.

Pipeline Design Pattern trong Laravel

Laravel sử dụng Pipeline ở một số nơi trong khuôn khổ của mình, nhưng nối bật nhất trong số đó chính là Middleware.

Trên thực tế, các Middleware này là các Pipeline dùng để thực hiện bất kì nhiệm vụ cần thiết nào khi có một yêu cầu gửi đến ứng dụng của chúng ta.

Mỗi middware sẽ có trách nhiệm cho một hành động duy nhất. Ví dụ như thiết lập cookie, ngăn chặn các cuộc tấn công CSRF.

Mỗi giai đoạn sẽ xử lý yêu cầu và chuyển nó sang giai đoạn tiếp theo hoặc từ chối yêu cầu và trả lại phản hồi HTTP thích hợp.

Nếu xem nhanh mã nguồn Illuminate\Foundation\Http\Kernel, bạn sẽ thấy cách các middware được thực thi thông qua Illuminate\Routing\Pipeline.

/**
 * Send the given request through the middleware / router.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Illuminate\Http\Response
 */
protected function sendRequestThroughRouter($request)
{
    $this->app->instance('request', $request);

    Facade::clearResolvedInstance('request');

    $this->bootstrap();

    return (new Pipeline($this->app))
                ->send($request)
                ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
                ->then($this->dispatchToRouter());
}

Cách sử dụng Laravel Pipeline

Request Filters

Giả sử, chúng ta đang trong quá trình phát triển một trang blog cho phép mọi người để lại nhận xét mà chủ đề bạn chia sẻ. Nhưng bạn có một mong muốn là những từ thô tục, phản cảm hay chứa những đoạn script phải được xóa bỏ.

Dựa trên yêu cầu đó, chúng ta có một quy trình trên giấy như sau:

1. Tiếp nhận dữ liệu từ người dùng.

2. Xóa bỏ các từ ngữ thô tục, phản cảm có trong nội dung.

3. Xóa bỏ các tag script có trong nội dung.

Dựa vào quy trình trên, chúng ta sẽ ra các class để xử lý từng nhiệm vụ như sau:

$pipes = [
    RemoveBadWords::class,
    RemoveScriptTags::class
];

Sau khi đã có danh sách các nhiệm vụ cần thực hiện, chúng ta sẽ bắt đầu thực hiện nó trong dự án của mình.

Trong thư mục app của Laravel, bạn hãy tạo một thư mục có tên là Filters.

Trong thư mục Filters, ban tạo tiếp một thư mục có tên là Requests.

Bạn hãy tạo file RemoveBadWords.php nằm trong thư mục app\Filters\Requests và có nội dung như sau:

<?php

namespace App\Filters\Requests;

use Closure;

class RemoveBadWords
{
    public function handle($content, Closure $next)
    {
        $badWords = [
            'ManhDanBlogs',
        ];
        $content = str_replace($badWords, '', $content);
        return  $next($content);
    }
}

Tiếp đó, tạo file RemoveScriptTags.php nằm trong thư mục app\Filters\Requests và có nội dung như sau:

<?php

namespace App\Filters\Requests;

use Closure;

class RemoveScriptTags
{
    public function handle($content, Closure $next)
    {
        $content = preg_replace('#<script(.*?)>(.*?)</script>#is', '', $content);
        return $next($content);
    }
}

Cuối cùng, chúng ta sẽ áp dụng Pipeline trong Controller như sau:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\User;
use Illuminate\Pipeline\Pipeline;
use App\Filters\Requests\RemoveBadWords;
use App\Filters\Requests\RemoveScriptTags;

class RequestController extends Controller
{
     /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(Request $request)
    {
        $name  = "ManhDanBlogs<script>alert('Website đang bị lỗi XSS!');</script>Đây là những gì còn xót lại";
        $pipes = [
            RemoveBadWords::class, // Input: ManhDanBlogs<script>alert('Website đang bị lỗi XSS!');</script>Đây là những gì còn xót lại
            RemoveScriptTags::class // Input: <script>alert('Website đang bị lỗi XSS!');</script>Đây là những gì còn xót lại
        ];
        $user = app(Pipeline::class)
        ->send($name)
        ->through($pipes)
        ->then(function ($name) {
            // Result: Đây là những gì còn xót lại
            return User::create(['name' => $name]);
        });
    }
}

Query Filters

Trong thư mục app của Laravel, bạn hãy tạo một thư mục có tên là Traits. Trong thư này, bạn hãy tạo file Filterable.php và có nội dung như sau:

<?php

namespace App\Traits;

use Illuminate\Pipeline\Pipeline;

trait Filterable
{
    public function scopeFilter($query, array $through)
    {
        return app(Pipeline::class)
               ->send($query)
               ->through($through)
               ->thenReturn();
    }
}

Tiếp theo, sử dụng Trait Filterable trong Model (trong bài viết này mình sử dụng model User) như sau:

<?php

namespace App\Models;

...
use App\Traits\Filterable;

class User extends Authenticatable
{
    use Filterable;

    ...
}

Trong thư mục Filters, ban tạo tiếp một thư mục có tên là Queries.

Bạn hãy tạo file NameFilter.php nằm trong thư mục app\Filters\Queries và có nội dung như sau:

<?php

namespace App\Filters\Queries;

class NameFilter
{
    public function handle($query, $next)
    {
        if (request()->name) {
           $query->where('name', request()->name);
        }

        return $next($query);
    }
}

Tiếp đó, chúng ta sẽ tạo tiếp file EmailFilter.php nằm trong thư mục app\Filters\Queries và có nội dung như sau:

<?php

namespace App\Filters\Queries;

class EmailFilter
{
    public function handle($query, $next)
    {
        if (request()->email) {
           $query->where('email', request()->email);
        }

        return $next($query);
    }
}

Cuối cùng, chúng ta sẽ áp dụng Pipeline trong Controller như sau:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\User;
use App\Filters\Queries\NameFilter;
use App\Filters\Queries\EmailFilter;

class QueryController extends Controller
{
     /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(Request $request)
    {
        $pipes = [
            NameFilter::class,
            EmailFilter::class,
        ];
        $users = User::query()->filter($pipes)->get();

        return $users;
    }
}

Tới đây, thì chúng ta đã trải nghiệm và thử áp dụng một vài trường hợp sử dụng Pipeline trong Laravel. Mình hy vọng qua bài viết này, bạn sẽ hiểu rõ Pipeline là gì, và cũng như áp dụng thành công trong dự án của bạn.

Nếu mọi người muốn góp ý cho bài viết này hoàn thiện hơn, bạn có thể liên lạc với mình qua trang contact.

Hy vọng, chúng ta sẽ gặp lại nhau trong bài viết tiếp theo. Cảm ơn bạn.

CÓ THỂ BẠN QUAN TÂM

Laravel Many to Many Eloquent Relationship

Laravel Many to Many Eloquent Relationship

Many To many Relationship là mối quan hệ hơi phức tạp hơn mối quan hệ 1 - 1 và 1- n. Ví dụ một user có thể có nhiều role khác nhau, trong đó role cũng được liên kết với nhiều user khác nhau. Vì vậy...

Laravel Socialite Login With Google

Laravel Socialite Login With Google

Google Google là một công cụ tìm kiếm trên internet. Nó sử dụng một thuật toán độc quyền được thiết kế để truy xuất và sắp xếp các kết quả tìm kiếm nhằm cung cấp các nguồn dữ liệu đáng tin cậy và ph...

Integrating CKFinder into CKEditor 5 in Laravel 11

Integrating CKFinder into CKEditor 5 in Laravel 11

CKEditor 5 CKEditor 5 là một trình soạn thảo văn bản phong phú JavaScript với nhiều tính năng và khả năng tùy chỉnh. CKEditor 5 có kiến trúc MVC hiện đại, mô hình dữ liệu tùy chỉnh và DOM ảo, mang...

Integrating CKEditor 5 in Laravel 10 using Vite

Integrating CKEditor 5 in Laravel 10 using Vite

CKEditor 5CKEditor 5 là một trình soạn thảo văn bản phong phú JavaScript với nhiều tính năng và khả năng tùy chỉnh. CKEditor 5 có kiến trúc MVC hiện đại, mô hình dữ liệu tùy chỉnh và DOM ảo, mang...

Laravel customize your API Versioning Route File

Laravel customize your API Versioning Route File

Trong khuôn khổ của Laravel, các route của api được tách thành một file duy nhất, đó là file api.php nằm trong thư mục routes . Nếu chúng ta muốn thêm version vào route api thì chúng ta sẽ làm như...

Laravel User Authentication

Laravel User Authentication

Trong hướng dẫn này, tôi sẽ hướng dẫn bạn xây dựng chức năng đăng nhập trong Laravel. Công bằng mà nói thì bạn có thể sử dụng Laravel UI hoặc JetStream để tự động tạo ra chức năng đăng nhập trong Lara...

Laravel Queues and Jobs

Laravel Queues and Jobs

Các công ty có thẻ gặp khó khăn trong việc quản lý các dịch vụ hoặc ứng dụng của họ. Ví dụ, các công ty các thực hiện gửi email cho hàng triệu người dùng hoặc thực hiện sao lưu dữ liệu. Tất cả các hoạ...

Encrypted HTTP Live Streaming with Laravel FFMpeg

Encrypted HTTP Live Streaming with Laravel FFMpeg

HTTP Live Streaming (HLS)  HTTP Live Streaming (HLS) là một trong những giao thức phát trực tuyến video được sử dụng rộng rãi nhất . Mặc dù nó được gọi là HTTP "live" streaming, nhưng nó được sử dụn...

Laravel UI Custom Email Password Reset Template

Laravel UI Custom Email Password Reset Template

Nếu bạn đang dùng thư viện laravel/ui để làm các chức năng liên quan đến authentication, và trong dự án của bạn, bạn cần thay đổi template email password reset thay vì sử dụng template email password...

ManhDanBlogs