Middleware Pattern trong PHP

BinlerdevBinlerdev
5 min read

1. Mở đầu

Bạn có bao giờ tưởng tượng code như một hành trình bánh hành (sandwich), cứ mỗi lớp lại có điều chỉnh một chút trước khi đến phần chính, rồi lại có lớp chỉnh sửa khi trở về? Đó chính là ý tưởng cơ bản của middleware trong lập trình PHP. Nó giúp chia nhỏ công việc, dễ quản lý và rõ ràng hơn. Quan trọng là: bạn không cần tự xử lý hết mọi thứ trong “phần giữa” của ứng dụng – cứ để middleware lo!


2. Middleware là gì?

Middleware trong PHP là lớp xử lý ở giữa (tức “middle”) – nằm giữa input (đầu vào) và output (đầu ra) của một hành động lõi (core action). Nó cho phép ta:

  1. Thay đổi input trước khi đến chức năng chính
  2. Chỉnh sửa output sau khi chức năng chính chạy xong (Doeken)

Bạn có thể tưởng tượng middleware như những lớp giấy gói quanh một hộp quà; từng lớp đều có thể thêm màu sắc, trang trí trước khi đưa đến bạn, rồi lại điều chỉnh khi bạn mở quà.


3. Bottom-up: Từ đơn giản đến nâng cao

3.1. Single Pass Middleware – lối đơn giản

  • Mỗi middleware nhận hai tham số:

    • $input: đầu vào (có thể là request, dữ liệu, số, v.v.)
    • $next: một callable để gọi middleware tiếp theo (Doeken)

Ví dụ minh họa:

function ($input, $next) {
  // Thao tác với input
  $input = trim($input);
  // Gọi middleware/Lõi tiếp theo
  $output = $next($input);
  // Thay đổi output trước khi trả về
  return strtoupper($output);
}

Trong đời sống: giống như bạn rút ví, kiểm tra (input), rồi cho vào túi (core action), rồi thêm cover chống xước (output).


3.2. Double Pass Middleware – lối cấp cao hơn

  • Nhận ba tham số: $input, $output mặc định, và $next để gọi middleware tiếp theo (Doeken)
  • Dùng khi bạn muốn ngắn mạch, tức là có thể quyết định ngưng ngay và trả về output mặc định, không cần gọi đến middleware khác.

Ví dụ minh họa:

function ($input, $output, $next) {
  if (empty($input)) {
    // Ngưng và trả về output mặc định
    return $output;
  }
  return $next($input, $output);
}

Tương ứng đời sống: bạn bước vào cửa, bạn có voucher miễn phí (output mặc định), nếu đủ điều kiện thì được vào, còn không thì cứ đi luôn—không cần chờ xét duyệt thêm.


4. Cách "gói" middleware quanh action lõi

Khái niệm “onion” (hành tây): từng middleware được xếp chồng quanh action lõi. Khi chạy:

  • Input đi vào middleware đầu tiên, mỗi lớp có thể chỉnh sửa rồi chuyền tiếp
  • Sau khi lõi xử lý, output quay ngược lại, mỗi lớp có thể tiếp tục điều chỉnh trước khi trả về (Doeken)

Mini code demo:

$action = fn(string $input): string => $input;

class ValueMiddleware {
  public function __construct(private string $value) {}
  public function __invoke(string $input, callable $next): string {
    $output = $next($this->value . $input);
    return $output . $this->value;
  }
}

$middlewares = [new ValueMiddleware('1'), new ValueMiddleware('2'), new ValueMiddleware('3')];
foreach ($middlewares as $middleware) {
  $action = fn(string $input): string => $middleware($input, $action);
}

echo $action('value'); // Kết quả: 123value123 :contentReference[oaicite:4]{index=4}

Giải thích: thứ tự “1”, “2”, “3” được thêm lần lượt vào input, và thêm tương ứng lần lượt vào output theo thứ tự ngược lại. Kết quả “123value123” là hoàn toàn hợp logic khi bạn nhìn từng bước.


5. Ví dụ thực tế trong lập trình

5.1. CSRF Validation Middleware

Input: request từ người dùng

  • Nếu token hợp lệ → gọi lên action
  • Nếu không hợp lệ → trả về 403 Forbidden ngay lập tức (Doeken)

Dễ hiểu như bạn đang quẹt thẻ vào thang máy: nếu không hợp lệ → cổng không mở, bạn bị dừng ở hành lang luôn.

5.2. Multi-tenant Middleware

  • Middleware kiểm tra URL để xác định khách hàng (tenant), chọn database tương ứng
  • Gắn thông tin tenant vào request để action lõi dễ đọc hơn (Doeken)

Ví như trong quán café: khi khách tới, nhân viên đọc mã bàn (URL), chọn đồ uống (CSDL), và phục vụ phù hợp.

5.3. Exception Handling Middleware

  • Middleware ngoài cùng bao quanh mọi thứ trong try-catch
  • Khi lỗi xảy ra → ghi log và trả về response kiểu lỗi cho người dùng (Doeken)

Giống như bảo vệ tòa nhà: nếu có sự cố xảy ra bên trong (lõi hoặc middleware khác), bảo vệ sẽ xử lý ngay, báo cáo thay vì để khách thấy cảnh hỗn loạn.


6. Tương tác nhẹ

Thử thách nhỏ: Trong thực tế của bạn, bạn nghĩ middleware có thể làm gì hỗ trợ trong ứng dụng đăng nhập? Ví dụ: thống kê lượt truy cập, cảnh báo đăng nhập bất thường… bạn hãy thử viết sơ đồ middleware cho tình huống đó nhé!


7. Kết luận & Lời khuyên

  • Middleware là cách cực hay để tách rời nhiệm vụ – mỗi lớp chỉ lo một việc, dễ test và bảo trì hơn.
  • Bắt đầu với dạng Single Pass cho dễ hiểu, rồi chuyển sang Double Pass nếu muốn tối ưu cách “short-circuit”.
  • Sử dụng middleware giúp core action (chức năng chính) tập trung vào logic cốt lõi, không bị xao nhãng bởi chuyện như kiểm tra quyền, logging, xử lý lỗi.

8. Tài liệu tham khảo thêm

  • Bài gốc: How the PHP Middleware Pattern works and can easily be applied trên doeken.org (Doeken)
  • Tài liệu về PSR-15 middleware chuẩn PHP (ujjwalojha.com.np)

Hy vọng bài viết này giúp bạn thấy middleware như một công cụ quen thuộc, không còn “xa vời”, và từ đó tự tin khám phá sâu hơn trong hành trình học lập trình!

0
Subscribe to my newsletter

Read articles from Binlerdev directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Binlerdev
Binlerdev