Xử lý form (biểu mẫu) với PHP
- 08-03-2023
- Toanngo92
- 0 Comments
Mục lục
Form HTML đơn giản
Một biểu mẫu (form) được sử dụng để lấy dữ liệu từ người dùng và chuyển nó đến máy chủ Web để xử lý, Nó được tạo bằng các thẻ HTML. Các loại form control (trình điều khiển biểu mẫu) khác nhau để thu thập dữ liệu bao gồm input, Checkboxes, Radio buttons, Submit and Reset buttons, Clickable controls,…
Dữ liệu có thể được gửi đến máy chủ để xử lý bằng các phương thức sau:
Phương thức GET: chỉ thị trình duyệt Web gửi thông tin người dùng được mã hóa được thêm vào cuối URL tới endpoint(có thể là tệp tin) xử lý. Trong phương pháp này, một dấu chấm hỏi (?) được thêm vào cuối URL. Dấu chấm hỏi này ngăn cách URL và thông tin biểu mẫu. Mỗi biến đầu vào trong một biểu mẫu có một thẻ Name và một giá trị được gán cho nó bởi người dùng.
Phương thức POST: chỉ thị trình duyệt Web gửi tất cả thông tin người dùng đến endpoint (có thể là tệp tin) xử lý, thông qua nội dung thông báo (message body) của một HTTP Request (yêu cầu HTTP). Phương thức này có khả năng truyền nhiều thông tin hơn, bởi vì không có giới hạn vật lý về lượng thông tin được truyền qua phần thân của yêu cầu HTTP.
Để hiểu hơn về 2 phương thức và kiến trúc của HTTP Request, có thể xem thêm bài viết Services communicate và khái niệm REST API.
PHP hỗ trợ một khái niệm gọi là biến super global (siêu toàn cục) đề cập đến các biến dựng sẵn luôn có sẵn trong mọi phạm vi. $_GET và $_POST là các biến super global được sử dụng để truy xuất dữ liệu từ biểu mẫu HTML đã gửi đã sử dụng các phương thức GET hoặc POST.
$_GET được biểu diễn bên trong dưới dạng một mảng các biến được truyền tới tập lệnh PHP hiện tại thông qua các tham số URL và $_POST dưới dạng một mảng các biến được truyền tới tập lệnh hiện tại thông qua phương thức HTTP POST.
Cú pháp truy cập dữ liệu được gửi đi từ phương thức GET và POST:
<?php
$_GET["variable_name'];
<?php
$_POST['variable_name'];
Trong đó, $_GET và $_POST là các siêu toàn cầu và luôn có thể truy cập được, bất kể phạm vi. Chúng có thể được truy cập từ bất kỳ chức năng, lớp hoặc tệp tin nào.
Ví dụ phương thức $_GET:
Bước 1: Tạo 1 file với tên bất kỳ ví dụ form_contact.php
<!-- html form example get method -->
<form action="test.php" method="get">
Name: <input type="text" name="name"><br>
E-mail: <input type="text" name="email"><br>
<input type="submit">
</form>
Bước 2: Tiếp tục tạo file tên test.php (tên file khớp với giá trị trong attribute action của thẻ <form/> trong file form_contact.php vừa tạo
<?php
if(!empty($_GET)){
echo $_GET['name'];
echo $_GET['email'];
}
Ví dụ phương thức $_POST:
Bước 1: Tạo 1 file với tên bất kỳ ví dụ login.php
<!-- html form example -->
<form action="process.php" method="post">
<input type="text" placeholder="username" name="username" />
<input type="text" placeholder="password" name="password" />
<input type="submit" value="Submit" />
</form>
Bước 2: Tiếp tục tạo file tên process.php (tên file khớp với giá trị trong attribute action của thẻ <form/> trong file login.php vừa tạo
<?php
if(!empty($_POST)){
echo $_POST['username'];
echo $_POST['password'];
}
Ví dụ 2: tạo một file hello.php như hình
Trong ví dụ, mã để tạo biểu mẫu đầu vào và tạo đầu ra được viết cùng nhau trong một tệp duy nhất. Khi mã được thực thi, người dùng có thể nhập dữ liệu vào trang biểu mẫu và nhấp vào nút gửi.
Sau đó, người dùng sẽ được chuyển hướng đến một phiên bản được làm mới của cùng một trang để truy xuất dữ liệu từ hộp văn bản bằng phương thức get và hiển thị nó với lời chào được cá nhân hóa.
<html>
<body>
<form action="hello.php" method="get">
First name: <input type="text" name="firstname"> <!-- corrected the input tag -->
<input type="submit" value="Submit"> <!-- added value attribute to submit button -->
</form>
Welcome
<?php
// Turn on error reporting for debugging
error_reporting(E_ALL);
echo $_GET["firstname"]; // corrected variable name and syntax
?>
</body>
</html>
Khi PHP gặp các biến không xác định, chẳng hạn như tên trước khi biểu mẫu được gửi, nó sẽ đưa ra các lỗi được hiển thị trong trình duyệt. Để tắt tính năng này, bạn có thể sử dụng error_reporting(0);
So sánh phương thức GET và POST
Cả hai phương thức get và post đều tạo ra một mảng (Ví dụ: array( key1 => value1, key2 => value2, key3 => value3, …)). Mảng chứa các cặp khóa và giá trị, trong đó, key chính là name của các control (input) trong form và value là dữ liệu đầu vào từ người dùng. Mỗi cặp key/value là URL được mã hóa bởi trình duyệt, trong đó khoảng trắng được thay thế bằng dấu + và các ký tự không phải chữ và số được thay thế bằng giá trị thập lục phân. Thông tin được mã hóa sau đó được gửi đến máy chủ.
Công dụng phương thức GET
Phương thức GET hiển thị tất cả các giá trị được gửi trong chính URL đó. Do đó, phương pháp này chỉ được khuyến nghị để gửi dữ liệu không nhạy cảm. Không nên sử dụng phương thức GET để gửi mật khẩu hoặc thông tin nhạy cảm khác. Phương pháp này cũng có giới hạn về lượng thông tin có thể được gửi. Giới hạn là khoảng 2048 ký tự. Tuy nhiên, có thể đánh dấu lại trang (lịch sử duyệt). Điều đó có nghĩa là, một trình duyệt có thể nhớ trang và bạn sẽ dễ dàng truy cập vào lần sau. Không giống như phương thức Đăng, phương thức get có thể được đánh dấu vì dữ liệu cần thiết cho yêu cầu được lưu trữ trong URL.
Công dụng phương thức GET
Phương thức POST không hiển thị các giá trị trong URL vì dữ liệu được gửi ở dạng gói và được duy trì trong một bộ xử lý giao tiếp riêng biệt. Nó không có giới hạn về lượng thông tin được gửi vì nó được gửi qua phần thân (body) của HTTP.
Hơn nữa, phương thức POST hỗ trợ chức năng nâng cao như đầu vào binary-multipart trong khi tải tệp lên máy chủ. Nó cũng hỗ trợ các loại dữ liệu khác như chuỗi, số, v.v. Tuy nhiên, vì các biến không được hiển thị trong URL nên không thể đánh dấu trang.
Giới thiệu biến $_REQUEST
Biến $_REQUEST trong PHP chứa các giá trị của $_GET, $_POST và $_COOKIE.
Cookie là một tệp văn bản được tạo trên máy tính của người dùng để lưu trữ thông tin người dùng để theo dõi mà các máy chủ Web có thể sử dụng. $_COOKIE là một mảng các biến được chuyển đến tập lệnh hiện tại thông qua HTTP Cookies.
Biến $_REQUEST trong PHP được sử dụng để lấy kết quả từ dữ liệu biểu mẫu được gửi bằng phương thức GET và POST.
Ví dụ:
<?php
error_reporting(0);
if ($_REQUEST["name"] || $_REQUEST["weight"]) {
echo "Welcome ".$_REQUEST['name']."<br />";
echo "You are ".$_REQUEST['weight']." kgs.";
exit;
}
?>
<html>
<body>
<form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>" method="POST">
Name: <input type="text" name="name" />
Weight: <input type="text" name="weight" />
<input type="submit" />
</form>
</body>
</html>
Trong mã này cũng vậy, biểu mẫu nhập và biểu mẫu hiển thị được viết trong cùng một chương trình. Tên và trọng lượng của người dùng được cung cấp làm đầu vào. Biến $_PHP_SELF được sử dụng để gửi dữ liệu biểu mẫu đã gửi đến cùng một trang khi gửi nút. $_ REQUEST được sử dụng để trả về giá trị tên và trọng lượng của người dùng.
Xác thực các trường biểu mẫu
Xác thực biểu mẫu là một nhiệm vụ quan trọng được thực hiện trước khi gửi dữ liệu do người dùng nhập vào biểu mẫu tới máy chủ/cơ sở dữ liệu. Các tập lệnh kiểm tra dữ liệu được nhập vào các trường theo các quy tắc xác thực đã được nhà phát triển đặt ra.
Nói chung, các trường đầu vào thường được sử dụng ở dạng PHP bao gồm:
- Các trường yêu cầu nhập hoặc tùy chọn
- Radio button
- Submit button
Trường văn bản (text fields)
Các trường văn bản trong biểu mẫu có thể chấp nhận kiểu nhập văn bản. Tên, địa chỉ, nghề nghiệp, v.v. là những ví dụ phổ biến về nhập văn bản. Hộp văn bản và vùng văn bản được sử dụng để chấp nhận văn bản ngắn và dài tương ứng.
Ví dụ:
<html>
<body>
<form action="login.php" method="post">
UserID: <input type="text" name="userID"><br><br>
Password: <input type="password" name="password"><br><br>
Company: <input type="text" name="company"><br><br>
Mobile Number: <input type="text" name="mobileNumber"><br><br>
<input type="submit" value="Submit">
Comments: <textarea name="comments" rows="6" cols="50"></textarea>
</form>
</body>
</html>
Output:
Radio button và select option
Các nút radio và select box (dropdown) được sử dụng trong các biểu mẫu khi người dùng có nhiều lựa chọn được đưa ra và phải chọn một tùy chọn nhất định.
<!DOCTYPE html>
<html>
<head>
<title>PHP Form Example</title>
</head>
<body>
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">
<!-- Radio Buttons -->
<label for="gender">Gender:</label><br>
<input type="radio" id="male" name="gender" value="male">
<label for="male">Male</label><br>
<input type="radio" id="female" name="gender" value="female">
<label for="female">Female</label><br>
<input type="radio" id="other" name="gender" value="other">
<label for="other">Other</label><br>
<!-- Select Option -->
<label for="country">Country:</label>
<select id="country" name="country">
<option value="">Select a country</option>
<option value="usa">USA</option>
<option value="canada">Canada</option>
<option value="uk">UK</option>
<option value="india">India</option>
<option value="australia">Australia</option>
</select><br><br>
<input type="submit" name="submit" value="Submit">
</form>
<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$gender = $_POST["gender"];
$country = $_POST["country"];
echo "<h3>You selected:</h3>";
echo "Gender: " . $gender . "<br>";
echo "Country: " . $country;
}
?>
</body>
</html>
Ở dạng này, chúng ta có hai yếu tố đầu vào – nút radio và tùy chọn chọn. Các nút radio cho phép người dùng chọn giới tính của họ, trong khi tùy chọn chọn cho phép họ chọn quốc gia của mình.
Lưu ý rằng chúng ta sử dụng hàm htmlspecialchars() (sẽ được nói ở ý dưới) để ngăn chặn các cuộc tấn công tập lệnh chéo trang (XSS) bằng cách chuyển đổi các ký tự đặc biệt trong đầu vào của người dùng thành các thực thể HTML tương đương.
Khi biểu mẫu được gửi, chúng ta sẽ kiểm tra phương thức yêu cầu bằng cách sử dụng $_SERVER[“REQUEST_METHOD”]. Nếu đó là yêu cầu POST, chúng ta truy xuất các giá trị của nút radio và chọn đầu vào tùy chọn bằng cách sử dụng biến siêu toàn cục (super global) $_POST. Cuối cùng, chúng ta hiển thị các giá trị đã chọn cho người dùng bằng cách sử dụng câu lệnh PHP echo.
Hộp chọn Checkbox
<html>
<body>
<h2>Checkbox Form</h2>
<form action="" method="POST">
<input type="checkbox" name="option[]" value="option1"><label>Option 1</label><br>
<input type="checkbox" name="option[]" value="option2"><label>Option 2</label><br>
<input type="checkbox" name="option[]" value="option3"><label>Option 3</label><br>
<input type="submit" name="submit" value="Submit">
</form>
<?php
if (isset($_POST['submit'])) {
$options = $_POST['option'];
foreach ($options as $option) {
echo $option . "<br>";
}
}
?>
</body>
</html>
Sử dụng htmlspecialchars() với các Form Element (Thành phần Biểu mẫu)
Form Element (thành phần biểu mẫu) là các phần tử được sử dụng bên trong thẻ biểu mẫu. Ở dạng này, nên sử dụng các phương thức như GET hoặc POST, các biến như $_SERVER[“PHP_SELF”] và hàm htmlspecialchars().
Ví dụ:
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
...
</form>
trong đó, htmlspeciaichars() là một hàm được sử dụng để chuyển đổi các ký tự đặc biệt thành các thực thể HTML. Nó thay thế các ký tự HTML như < và > bằng < và > (html entities). Điều này ngăn những kẻ tấn công thao túng mã bằng cách chèn mã HTML hoặc JavaScript (Tấn công tập lệnh chéo trang – XSS) vào biểu mẫu.
Xác thực dữ liệu biểu mẫu bằng PHP và hiển thị lỗi
Là bước đầu tiên trong quá trình xác thực, người ta phải chuyển tất cả các biến thông qua hàm htmlspecialchars() của PHP để xác thực dữ liệu biểu mẫu.
Hãy xem xét một tình huống trong đó người dùng độc hại cố gắng gửi siêu liên kết (hyperlink) trong trường văn bản nhằm nhận tên người dùng hoặc một số văn bản như vậy. Khi siêu liên kết được đăng lên trang được chuyển hướng, điều này có thể dẫn đến một hành động có hại.
Khi hàm htmlspecialchars() được sử dụng, nếu người dùng gửi dữ liệu như sau vào trường văn bản, dữ liệu đó sẽ không được thực thi dưới dạng siêu liên kết (hyperlink). Ví dụ:
<script>window.location.href = "https://hocvietcode.com"</script>
Điều này là do hàm htmlspecialchars() khiến dữ liệu được lưu bên trong dưới dạng HTML escape:
<script>window.location.href = "https://hocvietcode.com" </script>
Do đó, mã này hiện có thể được hiển thị an toàn trên một trang hoặc trong e-mail vì nó được coi là văn bản thay vì siêu liên kết. Mặt khác, nếu hàm htmlspecialchars() không được sử dụng với trường văn bản, thì kết quả sẽ không an toàn và có khả năng gây nguy hiểm.
Ngoài ra, hai hành động dưới có thể được thực hiện khi người dùng gửi biểu mẫu:
- Xóa (với việc sử dụng hàm trim() của PHP) các ký tự không cần thiết (space, tab, new line) từ dữ liệu đầu vào của người dùng
- Loại bỏ (với việc sử dụng hàm PHP Stripeslashes()) dấu gạch chéo ngược () khỏi dữ liệu đầu vào của người dùng
Bước tiếp theo là tạo một hàm sẽ thực hiện quy trình vệ sinh dữ liệu, điều này thuận tiện hơn so với việc viết lặp lại cùng một mã. Ví dụ:
<style>
.error {
color: red;
}
</style>
<?php
$nameErr = $emailErr = $messageErr = "";
$name = $email = $message = "";
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// Validate name
if (empty($_POST["name"])) {
$nameErr = "Name is required";
} else {
$name = test_input($_POST["name"]);
// check if name only contains letters and whitespace
if (!preg_match("/^[a-zA-Z-' ]*$/",$name)) {
$nameErr = "Only letters and white space allowed";
}
}
// Validate email
if (empty($_POST["email"])) {
$emailErr = "Email is required";
} else {
$email = test_input($_POST["email"]);
// check if e-mail address is well-formed
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$emailErr = "Invalid email format";
}
}
// Validate message
if (empty($_POST["message"])) {
$messageErr = "Message is required";
} else {
$message = test_input($_POST["message"]);
}
}
// Sanitize data
function test_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
?>
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">
Name: <input type="text" name="name" value="<?php echo $name;?>">
<span class="error"><?php echo $nameErr;?></span>
<br><br>
E-mail: <input type="text" name="email" value="<?php echo $email;?>">
<span class="error"><?php echo $emailErr;?></span>
<br><br>
Message: <textarea name="message" rows="5" cols="40"><?php echo $message;?></textarea>
<span class="error"><?php echo $messageErr;?></span>
<br><br>
Interests:
<br>
<input type="checkbox" id="interest1" name="interest[]" value="sports">
<label for="interest1"> Sports</label><br>
<input type="checkbox" id="interest2" name="interest[]" value="music">
<label for="interest2"> Music</label><br>
<input type="checkbox" id="interest3" name="interest[]" value="reading">
<label for="interest3"> Reading</label><br><br>
Select Gender:
<select name="gender">
<option value="">Select gender</option>
<option value="male">Male</option>
<option value="female">Female</option>
<option value="other">Other</option>
</select>
<br><br>
<input type="submit" name="submit" value="Submit">
</form>
<?php
echo "<h2>Your Input:</h2>";
echo $name;
echo "<br>";
echo $email;
echo "<br>";
echo $message;
echo "<br>";
if(isset($_POST['interest'])){
$interests_arr = $_POST['interest'];
$interests = implode(", ",$interests_arr);
echo $interests;
echo "<br>";
}
if(isset($_POST['gender'])){
echo $_POST['gender'];
}
?>
Output:
Sử dụng regex xác thực với ký tự đặc biệt
Trong một trường văn bản chẳng hạn như tên, người dùng chỉ có thể nhập các chữ cái và khoảng trắng. Số và ký tự đặc biệt không được phép trong trường tên. Trong tình huống đó, chúng ta có thể sử dụng hàm preg_match() (xem lại bài Biểu thức chính quy (Regular Expression) trong PHP) để kiểm tra trường tên để tìm các chữ cái, dấu gạch ngang, dấu nháy đơn và khoảng trắng:
$name = sanitize_data($_POST["name"]);
if (!preg_match("/^[a-zA-Z\s]+$/", $name)) {
$nameErr = "Only letters and white space allowed";
}
Một thông báo lỗi được hiển thị nếu giá trị được nhập cho trường tên không hợp lệ, Hàm preg_match() được sử dụng ở đây để tìm kiếm một chuỗi cho một mẫu. Nó trả về true nếu mẫu tồn tại và sai nếu mẫu không tồn tại.
Việc xác thực mật khẩu chứa các tiêu chí khác nhau, chẳng hạn như mật khẩu do người dùng nhập phải có ít nhất tám ký tự, với một ký tự viết hoa, một ký tự viết thường, một số và một ký tự đặc biệt.
Nếu tất cả các tiêu chí hoặc điều kiện phù hợp, thì mật khẩu người dùng mạnh, nếu không thì ‘một thông báo hiển thị cho biết mật khẩu yếu. Form sẽ hiển thị thông báo yêu cầu người dùng nhập mật khẩu có ít nhất tám ký tự, một chữ hoa, một ký tự thường, một số và một ký tự đặc biệt.
Ví dụ:
<form method="POST" action="register.php">
<label for="username">Username:</label>
<input type="text" id="username" name="username" required>
<label for="password">Password:</label>
<input type="password" id="password" name="password" pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9]).{6,}"
required title="Must contain at least 1 number ,1 lowercase letter, 1 uppercase letter, and 1 special character, and at least 6 or more characters long">
<input type="submit" value="Register">
</form>
Trong file register.php:
//Sanitize user inputs
$username = filter_var(trim($_POST["username"]),FILTER_SANITIZE_STRING);
$password = filter_var(trim($_POST["password"]),FILTER_SANITIZE_STRING);
//Validation for strong password
if(!preg_match('/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^a-zA-Z0-9])[A-Za-z\d@$!%*?&]{6,}$/', $password)){
echo "Invalid Password: Must contain at least one lowercase letter, one uppercase letter, one special character and at least 6 or more characters long.";
}
else{
//save the user data in database or log in the user
echo 'This is strong password !';
}
Bài tập
Bài 1:
Làm lại bài random coin với một nút bấm, mỗi khi người dùng bấm là random giá trị đồng xu
Bài 2:
Làm bài PT bậc 2 bằng thẻ Form và submit (yêu cầu người dùng nhập vào 3 số a,b,c sau khi bấm submit thì in ra kết quả x)
Bài 3:
Làm bài dưới với 2 cách sử dụng phương thức GET và POST