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

Generate PDF with Header and Footer on every page in Laravel

Generate PDF with Header and Footer on every page in Laravel

Hôm nay, trong bài viết này mình sẽ chia sẻ với các bạn cách dompdf mà header và footer sẽ được hiển thị ở tất cả các trang. Đây cũng là một vấn đề khá phổ biến, khi chúng ta phát triển các tính năng...

Laravel Factories, Seeder

Laravel Factories, Seeder

Trong bài viết này, tôi sẽ hướng dẫn các bạn về cách tạo dữ liệu giả trong cơ sở dữ liệu bằng cách sử dụng Laravel Factory và Seed trong Database Seeder. Để tạo model factory, bạn cần chạy lệnh sau...

Laravel TinyMCE 6 Image Upload

Laravel TinyMCE 6 Image Upload

TinyMCE TinyMCE là một trình soạn thảo  WYSIWYG  được xây dựng trên nền tảng Javascript, được phát triển dưới dạng mã nguồn mở theo giấy phép  MIT  bởi Tiny Technologies Inc. TinyMCE cho phép ngư...

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

Integrating TinyMCE in Laravel 10 using Vite

Integrating TinyMCE in Laravel 10 using Vite

TinyMCE TinyMCE là một trình soạn thảo WYSIWYG được xây dựng trên nền tảng Javascript, được phát triển dưới dạng mã nguồn mở theo giấy phép MIT bởi Tiny Technologies Inc. TinyMCE cho phép ngư...

Laravel Logging Of Database Queries

Laravel Logging Of Database Queries

Laravel là một Framework PHP mạnh mẽ và linh hoạt, giúp cho việc phát triển ứng dụng trở nên đơn giản và dễ dàng hơn. Một trong những tính năng hữu ích của Laravel là khả năng ghi nhật ký truy vấn...

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

Laravel Controllers

Laravel Controllers

Trong mô hình MVC, chữ "C" là từ viết tắt của Controller và nó đóng vai trò rất quan trọng để phân tích các logic business. Khi người dùng truy cập vào trình duyệt, nó sẽ đi đến route đầu tiên, sau đó...

Laravel Validate Video Duration

Laravel Validate Video Duration

Đôi khi trong dự án, chúng ta cần xác định thời lượng video được phép upload lên server. Nhưng rất tiếc, Laravel không cung cấp validate xác định thời lượng video để chúng ta thực hiện được. Vì vậy, t...

ManhDanBlogs