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

Defer in Laravel: Push Tasks to the Background

Defer in Laravel: Push Tasks to the Background

Deferred Functions trong Laravel Các phiên bản Laravel trước version 11, chúng ta thường sử dụng Queued Jobs cho phép thực hiện sắp xếp các tác vụ xử lý background . Nhưng đôi khi có những tác v...

Laravel Change Expire Time Cookie Remember

Laravel Change Expire Time Cookie Remember

Vấn đề Đôi khi, trang web của bạn chỉ muốn người dùng sử chức năng remembering users  trong 7 ngày hoặc là 30 ngày chẳng hạn. Nhưng Authentication của Laravel không cung cấp cho chúng ta tùy chọn đ...

Implementing Private User Folders with elFinder in Laravel

Implementing Private User Folders with elFinder in Laravel

elFinder elFinder là một trình quản lý tập tin mã nguồn mở dành cho web, được viết bằng JavaScript sử dụng jQuery UI. elFinder được phát triển dựa trên cảm hứng từ sự tiện lợi và đơn giản của chư...

Integrating CKFinder with Amazon S3 in Laravel

Integrating CKFinder with Amazon S3 in Laravel

CKFinder 3 CKFinder 3 là trình quản lý tập tin được tích hợp với CKEditor 4 và CKEditor 5. Nó giúp bạn dễ dàng đưa các tập tin và hình ảnh vào nội dung của Editor một cách an toàn. Đây là một tín...

Laravel CKEditor 5 Image Upload

Laravel CKEditor 5 Image Upload

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...

Google Drive as Filesystem in Laravel

Google Drive as Filesystem in Laravel

Đối với một số dự án, bạn cần phải sử dụng Google Drive (với tài khoản @gmail.com cá nhân hoặc tài khoản G Suite) làm nhà cung cấp bộ nhớ trong các dự án Laravel. Trong bài đăng này, tôi sẽ hướng d...

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 Socialite Login With Gitlab

Laravel Socialite Login With Gitlab

GitLab GitLab là kho lưu trữ Git dựa trên web cung cấp các kho lưu trữ mở và riêng tư miễn phí, các khả năng theo dõi vấn đề và wiki. Đây là một nền tảng DevOps hoàn chỉnh cho phép các chuyên gia...

Laravel Model

Laravel Model

Model là gì? Trong mô hình MVC, chữ “M” viết tắt là Model, Model dùng để xử lý logic nghiệp vụ trong bất kì ứng dụng dựa trên mô hình MVC. Trong Laravel, Model là lớp đại diện cho cấu trúc logic và...

ManhDanBlogs