การสร้าง Middleware ใน PHP
จากบทที่แล้ว เราได้รู้จักกับ Middleware และประโยชน์ของมัน ในบทนี้ เราจะมาลงมือสร้าง Middleware ของเราเองใน PHP กันครับ
การสร้าง Class สำหรับ Middleware
ขั้นตอนแรกคือการสร้าง Class สำหรับ Middleware ของเรา Class นี้จะต้องมี method ที่จะถูกเรียกใช้งานเมื่อ Request ผ่านเข้ามา โดยทั่วไปเราจะเรียก method นี้ว่า handle หรือ process ครับ
ตัวอย่างเช่น หากเราต้องการสร้าง Middleware ที่ตรวจสอบว่า API Key ถูกต้องหรือไม่ เราสามารถสร้าง Class ชื่อ ApiKeyMiddleware ได้ดังนี้:
<?php
class ApiKeyMiddleware {
public function handle($request, $next) {
// Logic การตรวจสอบ API Key จะอยู่ที่นี่
// $request คือข้อมูล Request ที่ส่งเข้ามา
// $next คือ function ที่จะเรียก Middleware ตัวถัดไป หรือ Endpoint ที่ต้องการ
// ตัวอย่าง: ตรวจสอบว่ามี Header ชื่อ 'X-API-Key' หรือไม่
if (!isset($_SERVER['HTTP_X_API_KEY'])) {
// ถ้าไม่มี API Key ให้ส่ง Error กลับไป
http_response_code(401); // Unauthorized
echo json_encode(['error' => 'API Key is required']);
exit; // หยุดการทำงาน
}
// ตัวอย่าง: ตรวจสอบว่า API Key ถูกต้องหรือไม่ (สมมติว่าเรามี API Key ที่ถูกต้องเก็บไว้ในตัวแปร $validApiKey)
$validApiKey = 'YOUR_SECRET_API_KEY'; // แทนค่าด้วย API Key ที่ถูกต้องของคุณ
$apiKey = $_SERVER['HTTP_X_API_KEY'];
if ($apiKey !== $validApiKey) {
// ถ้า API Key ไม่ถูกต้อง ให้ส่ง Error กลับไป
http_response_code(403); // Forbidden
echo json_encode(['error' => 'Invalid API Key']);
exit; // หยุดการทำงาน
}
// ถ้า API Key ถูกต้อง ให้เรียก Middleware ตัวถัดไป หรือ Endpoint ที่ต้องการ
return $next($request);
}
}
คำอธิบาย:
class ApiKeyMiddleware: ประกาศ Class ชื่อApiKeyMiddlewarepublic function handle($request, $next): Methodhandleเป็น method หลักของ Middleware นี้ รับ parameter 2 ตัว:$request: ข้อมูล Request ที่ถูกส่งเข้ามา (ในตัวอย่างนี้เราไม่ได้ใช้โดยตรง แต่ในกรณีอื่นๆ อาจมีการเข้าถึงข้อมูลจาก Request เช่น body, headers, หรือ parameters)$next: Function ที่จะเรียก Middleware ตัวถัดไป หรือ Endpoint ที่ต้องการ ถ้า Middleware นี้ตรวจสอบสำเร็จ
if (!isset($_SERVER['HTTP_X_API_KEY'])): ตรวจสอบว่ามี HTTP Header ชื่อX-API-Keyหรือไม่ (เราจะส่ง API Key ผ่าน Header ในตัวอย่างนี้)http_response_code(401): ถ้าไม่มี API Key ให้ส่ง HTTP Status Code 401 (Unauthorized) กลับไปecho json_encode(['error' => 'API Key is required']): ส่ง JSON response กลับไปพร้อมข้อความ errorexit: หยุดการทำงานของ script ทันที เพื่อป้องกันการเข้าถึง Endpoint โดยไม่ได้รับอนุญาต$validApiKey = 'YOUR_SECRET_API_KEY': กำหนด API Key ที่ถูกต้อง (ควรเก็บไว้ในที่ปลอดภัยกว่านี้ เช่น environment variable)if ($apiKey !== $validApiKey): ตรวจสอบว่า API Key ที่ส่งมาตรงกับ API Key ที่ถูกต้องหรือไม่http_response_code(403): ถ้า API Key ไม่ถูกต้อง ให้ส่ง HTTP Status Code 403 (Forbidden) กลับไปreturn $next($request): ถ้า API Key ถูกต้อง ให้เรียก function$nextเพื่อดำเนินการต่อ (เรียก Middleware ตัวถัดไป หรือ Endpoint ที่ต้องการ)
การ Implement Logic ใน Middleware
ใน Method handle เราจะเขียน Logic ที่เราต้องการให้ Middleware ทำงาน ตัวอย่างเช่น:
- ตรวจสอบ API Key
- ตรวจสอบสิทธิ์การเข้าถึง (Authorization)
- บันทึก Log การเข้าถึง
- แปลงข้อมูล Request
- ตรวจสอบความถูกต้องของข้อมูล (Validation)
ข้อควรระวัง:
- Middleware ควรทำงานให้เร็วที่สุดเท่าที่จะทำได้ เพราะมันจะถูกเรียกใช้งานทุกครั้งที่มี Request เข้ามา
- Middleware ควรจัดการเฉพาะ Logic ที่เกี่ยวข้องกับ Request และ Response เท่านั้น ไม่ควรมี Logic ทางธุรกิจที่ซับซ้อน
การเรียกใช้งาน Middleware
เมื่อเราสร้าง Class Middleware แล้ว เราจะต้องเรียกใช้งานมันก่อนที่จะเข้าถึง Endpoint ที่เราต้องการ วิธีการเรียกใช้งานขึ้นอยู่กับโครงสร้างของ Application ของเรา
ตัวอย่างการเรียกใช้งานแบบง่ายๆ (ไม่มี Framework):
<?php
require_once 'ApiKeyMiddleware.php'; // Include ไฟล์ Middleware
$middleware = new ApiKeyMiddleware();
// สร้าง function ที่จะจำลอง Endpoint
$endpoint = function($request) {
http_response_code(200);
echo json_encode(['message' => 'Welcome to the API!']);
};
// เรียก Middleware ก่อนเรียก Endpoint
$middleware->handle($_REQUEST, $endpoint);
คำอธิบาย:
require_once 'ApiKeyMiddleware.php': Include ไฟล์ที่ ClassApiKeyMiddlewareถูกประกาศไว้$middleware = new ApiKeyMiddleware(): สร้าง Instance ของ ClassApiKeyMiddleware$endpoint = function($request) { ... }: สร้าง Anonymous Function ที่จะทำหน้าที่เป็น Endpoint ของเรา (ในความเป็นจริง Endpoint จะซับซ้อนกว่านี้)$middleware->handle($_REQUEST, $endpoint): เรียก Methodhandleของ Middleware โดยส่งข้อมูล Request ($_REQUEST) และ Function$endpointเป็น Parameter
ในตัวอย่างนี้ เราเรียก $middleware->handle() โดยตรงก่อนที่จะเรียก Endpoint ซึ่งทำให้ Middleware ทำงานก่อนเสมอ
กรณีใช้งานจริง:
ใน Application ขนาดใหญ่ เรามักจะใช้ Framework เช่น Laravel หรือ Symfony ซึ่งมีระบบ Middleware ที่จัดการได้ง่ายกว่า ตัวอย่างเช่นใน Laravel เราสามารถกำหนด Middleware ใน app/Http/Kernel.php และใช้งานได้โดยระบุชื่อ Middleware ใน Route Definition:
// ตัวอย่าง Route Definition ใน Laravel
Route::get('/api/users', 'UserController@index')->middleware('api.key');
ในตัวอย่างนี้ Route /api/users จะถูกป้องกันด้วย Middleware ชื่อ api.key ซึ่งเราได้กำหนดไว้ใน Kernel
ข้อผิดพลาดที่พบบ่อย
- ลืม Include ไฟล์ Middleware: ตรวจสอบให้แน่ใจว่าคุณได้ Include ไฟล์ที่ Class Middleware ถูกประกาศไว้
- Parameter ไม่ถูกต้อง: ตรวจสอบว่าคุณส่ง Parameter ที่ถูกต้องให้กับ Method
handle(Request และ Next Function) - ไม่เรียก
$next(): ถ้าคุณไม่เรียก$next()ใน Middleware Endpoint จะไม่ถูกเรียกใช้งาน - Headers ถูกส่งไปแล้ว: ถ้าคุณพยายามส่ง Headers หลังจากที่ได้ส่ง content ไปแล้ว จะเกิด Error ขึ้น ตรวจสอบให้แน่ใจว่าคุณส่ง Headers ก่อนที่จะ
echoหรือprintcontent ใดๆ - API Key ไม่ถูกต้อง: ตรวจสอบ API Key ที่ใช้ว่าถูกต้องและไม่ได้หมดอายุ
สรุป
ในบทนี้ เราได้เรียนรู้วิธีการสร้าง Middleware ใน PHP ซึ่งเป็นเครื่องมือที่มีประโยชน์ในการจัดการ Request และ Response ของ API เราได้สร้าง Class สำหรับ Middleware, Implement Logic ใน Middleware, และเรียนรู้วิธีการเรียกใช้งาน Middleware ทั้งแบบง่ายๆ และใน Framework อย่าง Laravel ในบทต่อไป เราจะมาดูวิธีการใช้ Middleware สำหรับ Authentication กันครับ