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 Task Scheduling

Laravel Task Scheduling

Trong các ứng dụng lớn, bạn cần lên lịch định kì cho các công việc bằng Cron jobs.  Tại số một số thời điểm, việc quản lý các cron jobs trở nên cồng kềnh và khó khăn hơn. Laravel Scheduler là một côn...

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

Laravel Socialite Login With Github

GitHub GitHub là một nền tảng phát triển phần mềm trực tuyến. Nó được sử dụng để lưu trữ, theo dõi và cộng tác trong các dự án phần mềm. Nó giúp các nhà phát triển dễ dàng chia sẻ các tập tin mã...

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

Easy Laravel Reverb Setup For Beginners

Easy Laravel Reverb Setup For Beginners

Laravel Reverb Lần đầu tiên, Laravel ra mắt một official package cho phép bạn xây dựng một Websocket Server. Trước đây, chúng ta phải sử dụng package bên thứ 3 như Laravel Websocket. Reverb được...

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

Laravel Accessor and Mutator

Laravel Accessor and Mutator

Trong bài viết này, tôi sẽ hướng dẫn các bạn cách để format các Eloquent Attributes bằng cách sử dụng tính năng Laravel Accessors and Mutators. Accessors được sử dụng để format các thuộc tính khi c...

Laravel UI Password Reset Expired

Laravel UI Password Reset Expired

Trong thư viện laravel/ui, thì chức năng password reset dù cho token có hết hạn thì vẫn có truy cập vào trang password reset, đến khi bạn submit form thì mới thông báo là token đã hết hạn. Nhưng có mộ...

Laravel Custom Request

Laravel Custom Request

Nếu bạn có một form để người dùng nhập dữ liệu và bạn muốn kiểm tra dữ liệu đầu vào trước khi lưu xuống database chẳng hạn thì bạn có 2 cách sau đây: Cách 1: Bạn thêm validate trực tiếp vào hàm sto...

ManhDanBlogs