Kodokon kodokon.com

แบบฟอร์ม: การรับและการตรวจสอบข้อมูล

จัดการแบบฟอร์มอย่างมืออาชีพ: เลือกเมท็อด HTTP ที่ถูกต้อง ตรวจสอบข้อมูลนำเข้าอย่างเข้มงวด และแสดงผลซ้ำอย่างปลอดภัย

9 นาที · 3 คำถาม

เปิดบทเรียนนี้ใน Kodokon

แบบฟอร์มคือจุดสัมผัสแรกระหว่างผู้ใช้ของคุณกับโค้ด PHP เมท็อด get วางข้อมูลไว้ใน URL (?q=pizza) เหมาะอย่างยิ่งสำหรับการค้นหาหรือการกรอง เพราะหน้าเว็บสามารถถูกบุ๊กมาร์กและแชร์ต่อได้ ส่วนเมท็อด post พาข้อมูลไปกับส่วนเนื้อหา (body) ของคำขอ มันคือเมท็อดที่จำเป็นทุกครั้งที่คำขอ เปลี่ยนแปลงบางอย่าง (การสร้างบัญชี การสั่งซื้อ การลบ) หรือพาข้อมูลอ่อนไหว PHP เก็บค่าที่ได้รับไว้ในซูเปอร์โกลบอล $_GET และ $_POST

HTML
<form action="search.php" method="get">
  <label for="q">Search</label>
  <input id="q" name="q" type="text">
  <button type="submit">Search</button>
</form>
<?php
$query = trim($_GET['q'] ?? '');

if ($query !== '') {
    echo "<p>You are searching for: " .
        htmlspecialchars($query, ENT_QUOTES) . "</p>";
}
?>
search.php: แบบฟอร์มและการจัดการของมันในหน้าเดียวกัน

กฎมืออาชีพข้อแรก: อย่าเชื่อข้อมูลที่เข้ามาเด็ดขาด ผู้ใช้สามารถส่งอะไรก็ได้ รวมถึงค่าที่ปลอมแปลงขึ้นมาโดยไม่ได้มาจากแบบฟอร์มของคุณ ฟังก์ชัน filter_input() อ่านและตรวจสอบค่าในขั้นตอนเดียว มันคืนค่าที่ผ่านการตรวจสอบแล้ว คืน false ถ้าค่าไม่ถูกต้อง และคืน null ถ้าไม่มีฟิลด์นั้น สามกรณีที่ต้องแยกให้ออกในข้อความแจ้งข้อผิดพลาดของคุณ

PHP
<?php

declare(strict_types=1);

$errors = [];

$email = filter_input(
    INPUT_POST,
    'email',
    FILTER_VALIDATE_EMAIL
);

$age = filter_input(
    INPUT_POST,
    'age',
    FILTER_VALIDATE_INT,
    ['options' => ['min_range' => 18, 'max_range' => 120]]
);

$name = trim((string) ($_POST['name'] ?? ''));

if ($name === '' || mb_strlen($name) > 50) {
    $errors[] = "Name required (50 characters max).";
}

if (!is_string($email)) {
    $errors[] = "Invalid email address.";
}

if (!is_int($age)) {
    $errors[] = "Invalid age (between 18 and 120).";
}

if ($errors === []) {
    echo "Registration valid.";
}
การตรวจสอบการสมัครสมาชิกด้วย filter_input()

เมื่อการตรวจสอบล้มเหลว อย่าส่งแบบฟอร์มเปล่ากลับไป จงแสดงค่าที่ผู้ใช้พิมพ์ไว้ซ้ำ (แบบฟอร์มแบบ "เหนียว" หรือ sticky) พร้อมข้อความแจ้งข้อผิดพลาดข้าง ๆ ฟิลด์ที่เกี่ยวข้อง ค่าใด ๆ ที่นำมาแสดงซ้ำต้องผ่าน htmlspecialchars() เสมอ นั่นคือสิ่งที่ทำให้แท็กเป็นกลางและป้องกันการฉีดสคริปต์

HTML
<?php
$name = trim($_POST['name'] ?? '');
$hasError = isset($_POST['name']) && $name === '';
$safeName = htmlspecialchars($name, ENT_QUOTES);
?>
<form method="post" action="">
  <label for="name">Your name</label>
  <input id="name" name="name"
    value="<?= $safeName ?>">
  <?php if ($hasError): ?>
    <p>Name is required.</p>
  <?php endif; ?>
  <button type="submit">Submit</button>
</form>
แบบฟอร์มแบบเหนียว: ข้อมูลที่กรอกยังคงอยู่แม้เกิดข้อผิดพลาด

ทดสอบความรู้

ตรวจสอบว่าคุณจำประเด็นสำคัญของบทเรียนนี้ได้ครบถ้วน

  1. เมท็อด HTTP ใดที่เหมาะสมกับแบบฟอร์มที่ใช้สร้างบัญชีผู้ใช้?
    • GET เพื่อให้ข้อมูลยังคงมองเห็นได้ใน URL
    • POST เพราะคำขอเปลี่ยนสถานะของเซิร์ฟเวอร์ และข้อมูลต้องไม่ปรากฏใน URL
    • ใช้อันไหนก็ได้ เป็นเรื่องของสไตล์
  2. filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL) คืนค่าอะไรถ้าฟิลด์นั้นไม่ได้ถูกส่งมาเลย?
    • false
    • สายอักขระว่าง
    • null
    • มันโยนข้อยกเว้น (exception)
  3. ทำไมต้องส่งค่าผ่าน htmlspecialchars() ก่อนนำมาแสดงซ้ำในหน้าเว็บ?
    • เพื่อทำให้แท็ก HTML เป็นกลางและป้องกันการฉีดสคริปต์ (ช่องโหว่ XSS)
    • เพื่อแก้คำผิดโดยอัตโนมัติ
    • เพื่อบีบอัดค่าและทำให้แสดงผลเร็วขึ้น