Superglobals: $_REQUEST
ในบทเรียนก่อนหน้า เราได้เรียนรู้เกี่ยวกับ $_GET และ $_POST ซึ่งเป็น Superglobal arrays ที่ใช้ในการรับข้อมูลจาก HTTP GET และ POST methods ตามลำดับ ในบทนี้ เราจะมาทำความรู้จักกับ $_REQUEST ซึ่งเป็น Superglobal array อีกตัวหนึ่งที่น่าสนใจ แต่ก็ต้องใช้งานด้วยความระมัดระวัง
ความหมายของ $_REQUEST
$_REQUEST เป็น Superglobal array ใน PHP ที่เก็บข้อมูลที่ส่งมายังสคริปต์ PHP ไม่ว่าจะเป็นข้อมูลที่ส่งผ่าน $_GET, $_POST, หรือ $_COOKIE นั่นหมายความว่า $_REQUEST จะรวมข้อมูลจากทั้งสามแหล่งนี้ไว้ใน array เดียว
ตัวอย่าง:
<form action="process.php" method="post">
<input type="text" name="username" value="JohnDoe"><br>
<input type="submit" value="Submit">
</form>
<a href="process.php?action=delete">Delete User</a>
ในตัวอย่างนี้ เรามีฟอร์มที่ส่งข้อมูล username ผ่าน POST และลิงก์ที่ส่ง action ผ่าน GET หากเราเข้าถึง process.php ด้วยวิธีใดวิธีหนึ่งหรือทั้งสองวิธี เราสามารถเข้าถึงข้อมูลเหล่านั้นได้จาก $_REQUEST
<?php
// process.php
if (isset($_REQUEST['username'])) {
echo "Username: " . $_REQUEST['username'] . "<br>";
}
if (isset($_REQUEST['action'])) {
echo "Action: " . $_REQUEST['action'] . "<br>";
}
?>
หากเราส่งฟอร์ม เราจะได้ผลลัพธ์:
Username: JohnDoe
หากเราคลิกที่ลิงก์ เราจะได้ผลลัพธ์:
Action: delete
หากเราส่งทั้งฟอร์มและคลิกที่ลิงก์ (ซึ่งไม่ค่อยเกิดขึ้นจริง แต่เป็นไปได้หากมีการจัดการ URL ที่ซับซ้อน) เราจะได้ผลลัพธ์:
Username: JohnDoe
Action: delete
ข้อดีและข้อเสียของการใช้ $_REQUEST
ข้อดี:
- ความสะดวก: สามารถเข้าถึงข้อมูลจากทั้ง GET, POST และ COOKIE ได้ใน array เดียว
- ความง่ายในการใช้งาน: โค้ดอาจสั้นลงเมื่อไม่ต้องตรวจสอบว่าข้อมูลมาจาก GET หรือ POST
ข้อเสีย:
- ความไม่ชัดเจน: ไม่สามารถทราบได้ว่าข้อมูลมาจาก GET, POST หรือ COOKIE ทำให้ยากต่อการดีบักและบำรุงรักษา
- ความเสี่ยงด้านความปลอดภัย: อาจทำให้เกิดช่องโหว่ด้านความปลอดภัยได้ง่ายขึ้น หากไม่ได้ตรวจสอบและ sanitize ข้อมูลอย่างเหมาะสม
- ลำดับความสำคัญ: หากมีข้อมูลชื่อเดียวกันจาก GET และ POST, PHP จะใช้ข้อมูลจากแหล่งใดแหล่งหนึ่ง (ขึ้นอยู่กับการตั้งค่า
variables_orderในphp.iniซึ่งอาจแตกต่างกันในแต่ละ environment) ทำให้เกิดพฤติกรรมที่ไม่คาดฝัน
ควรระมัดระวังเรื่อง Security
เนื่องจาก $_REQUEST รวมข้อมูลจากหลายแหล่ง ทำให้มีความเสี่ยงด้านความปลอดภัยสูง หากไม่ได้จัดการอย่างระมัดระวัง ผู้ไม่ประสงค์ดีอาจใช้ประโยชน์จากช่องโหว่นี้เพื่อโจมตีเว็บไซต์ของเราได้
ข้อควรระวัง:
- หลีกเลี่ยงการใช้งาน $_REQUEST โดยไม่จำเป็น: หากทราบว่าข้อมูลมาจาก GET หรือ POST แน่นอน ให้ใช้
$_GETหรือ$_POSTโดยตรง - ตรวจสอบแหล่งที่มาของข้อมูล: หากจำเป็นต้องใช้
$_REQUESTให้ตรวจสอบว่าข้อมูลมาจาก GET, POST หรือ COOKIE ก่อนใช้งาน โดยใช้isset($_GET['...']),isset($_POST['...'])หรือisset($_COOKIE['...']) - Sanitize ข้อมูล: ไม่ว่าข้อมูลจะมาจากแหล่งใดก็ตาม ต้องทำการ sanitize ข้อมูลก่อนนำไปใช้งานเสมอ เพื่อป้องกัน XSS (Cross-Site Scripting) และ SQL Injection
- Validate ข้อมูล: ตรวจสอบว่าข้อมูลเป็นไปตามรูปแบบที่คาดหวัง เช่น ประเภทข้อมูล, ความยาว, ช่วงของค่า
ตัวอย่างการ sanitize ข้อมูล:
<?php
// สมมติว่าเราได้รับ username จาก $_REQUEST
if (isset($_REQUEST['username'])) {
$username = $_REQUEST['username'];
// Sanitize ข้อมูล
$username = htmlspecialchars($username, ENT_QUOTES, 'UTF-8');
// Validate ข้อมูล
if (strlen($username) > 50) {
echo "Username ยาวเกินไป";
} else {
// นำ username ที่ sanitize แล้วไปใช้งาน
echo "Username: " . $username;
}
}
?>
ในตัวอย่างนี้ เราใช้ htmlspecialchars() เพื่อแปลง characters พิเศษให้เป็น HTML entities เพื่อป้องกัน XSS และตรวจสอบความยาวของ username เพื่อป้องกันการใส่ข้อมูลที่ยาวเกินไป
กรณีใช้งานจริงและข้อผิดพลาดที่พบบ่อย
กรณีใช้งาน:
แม้ว่าโดยทั่วไปแล้วไม่แนะนำให้ใช้ $_REQUEST แต่ก็มีบางกรณีที่อาจจำเป็นต้องใช้งาน เช่น เมื่อต้องการสร้าง API ที่รองรับทั้ง GET และ POST โดยไม่ต้องการเขียนโค้ดซ้ำซ้อน
ตัวอย่าง:
<?php
// api.php
// ตรวจสอบว่า action ถูกส่งมา
if (isset($_REQUEST['action'])) {
$action = $_REQUEST['action'];
switch ($action) {
case 'get_user':
// ดึงข้อมูลผู้ใช้
$user_id = isset($_REQUEST['user_id']) ? intval($_REQUEST['user_id']) : null;
if ($user_id) {
// ดึงข้อมูลผู้ใช้จากฐานข้อมูล
// ...
echo json_encode($user);
} else {
http_response_code(400); // Bad Request
echo json_encode(['error' => 'Missing user_id']);
}
break;
case 'create_user':
// สร้างผู้ใช้ใหม่
$username = isset($_REQUEST['username']) ? htmlspecialchars($_REQUEST['username'], ENT_QUOTES, 'UTF-8') : null;
$email = isset($_REQUEST['email']) ? filter_var($_REQUEST['email'], FILTER_VALIDATE_EMAIL) : null;
if ($username && $email) {
// สร้างผู้ใช้ในฐานข้อมูล
// ...
echo json_encode(['message' => 'User created successfully']);
} else {
http_response_code(400); // Bad Request
echo json_encode(['error' => 'Missing username or email']);
}
break;
default:
http_response_code(400); // Bad Request
echo json_encode(['error' => 'Invalid action']);
}
} else {
http_response_code(400); // Bad Request
echo json_encode(['error' => 'Missing action']);
}
?>
ในตัวอย่างนี้ เราสร้าง API ที่รองรับสอง action คือ get_user และ create_user โดยใช้ $_REQUEST เพื่อรับข้อมูลจากทั้ง GET และ POST แต่ก็มีการตรวจสอบและ sanitize ข้อมูลอย่างละเอียด
ข้อผิดพลาดที่พบบ่อย:
- ลืม sanitize ข้อมูล: เป็นข้อผิดพลาดที่พบบ่อยที่สุดและนำไปสู่ช่องโหว่ด้านความปลอดภัย
- ไม่ตรวจสอบแหล่งที่มาของข้อมูล: ทำให้ไม่สามารถทราบได้ว่าข้อมูลมาจาก GET, POST หรือ COOKIE
- พึ่งพาการตั้งค่า
variables_order: ทำให้โค้ดทำงานแตกต่างกันในแต่ละ environment - ใช้ $_REQUEST โดยไม่จำเป็น: ทำให้โค้ดอ่านยากและบำรุงรักษายาก
สรุป
$_REQUEST เป็น Superglobal array ที่รวมข้อมูลจาก GET, POST และ COOKIE ทำให้สะดวกในการใช้งาน แต่ก็มีความเสี่ยงด้านความปลอดภัยสูง หากไม่ได้จัดการอย่างระมัดระวัง ควรหลีกเลี่ยงการใช้งาน $_REQUEST โดยไม่จำเป็น และให้ความสำคัญกับการตรวจสอบและ sanitize ข้อมูลเสมอ ในบทเรียนถัดไป เราจะมาเรียนรู้เกี่ยวกับ Superglobal array อีกตัวหนึ่งที่ใช้ในการจัดการ session นั่นคือ $_SESSION