$_GET là một mảng chứa query string của URL, nên article.php?id=42&lang=en cho bạn $_GET['id'] === '42' và $_GET['lang'] === 'en'. $_POST là một mảng chứa các trường của form gửi bằng method="post". Hãy đọc cả hai kèm giá trị mặc định, $_GET['id'] ?? null, vì khóa sẽ không tồn tại mỗi khi thiếu tham số.
Chạy khối code, rồi bấm vào các liên kết: mỗi lần bấm, script chạy lại với $_GET được lấy từ query string của liên kết.
$_GET['lang'] là bất cứ thứ gì URL ghi, không chỉ ba liên kết bạn đã in ra. Ai cũng có thể gõ ?lang=<script> vào thanh địa chỉ, đó là lý do khối code tra giá trị trong $languages thay vì in thẳng nó ra, và escape ở chỗ duy nhất có in dữ liệu từ request.
Đọc một số từ query string
Mọi giá trị trong $_GET đều là chuỗi. Với số trang, hãy kiểm tra và chuyển kiểu trong một bước bằng filter_var() và dùng giá trị mặc định khi giá trị bị thiếu, không phải số hoặc nằm ngoài khoảng. Bấm qua các trang, rồi thử các liên kết Page 999 và Page abc.
filter_var() trả về số nguyên 3 với "3" và trả về tùy chọn default với mọi chuỗi khác, nên $page luôn là một số nguyên dùng được. Trang filter_var liệt kê các bộ kiểm tra khác.
Đọc dữ liệu form với $_POST
Form có method="post" gửi các trường trong phần thân request, và PHP đặt chúng vào $_POST theo name của từng ô nhập. $_SERVER['REQUEST_METHOD'] cho bạn biết request hiện tại là lần truy cập đầu (GET) hay là lần submit (POST). Điền form rồi nhấn Send để xem cả hai.
Ô văn bản để trống vẫn được gửi đi, dưới dạng "", nên sau khi submit $_POST['title'] vẫn tồn tại dù người truy cập không gõ gì. Trên máy chủ, REQUEST_METHOD luôn có giá trị; ?? 'GET' chỉ giúp script không báo lỗi khi bạn chạy tệp bằng php trên dòng lệnh. Mẫu đầy đủ để kiểm tra và hiển thị lại form có ở trang form.
Form tìm kiếm với method="get"
Dùng GET cho form mà kết quả nên là một URL chia sẻ được, như ô tìm kiếm. Trình duyệt biến các trường thành query string (?q=sort&level=beginner) và script đọc chúng từ $_GET, y hệt một liên kết. Hãy tìm array hoặc string.
Tạo liên kết với http_build_query
Tự viết "?q=$q&page=2" sẽ hỏng ngay khi $q chứa khoảng trắng, & hoặc #. http_build_query() mã hóa mọi giá trị giúp bạn, và kết quả đi qua htmlspecialchars() khi được đặt vào href, vì trong HTML & nên là &.
parse_str() với hai đối số chính là cách PHP tạo $_GET từ một query string, nên rất tiện khi kiểm thử. Luôn truyền đối số thứ hai; dạng một đối số cũ vốn tạo ra biến đã bị bỏ trong PHP 8.
$_REQUEST và lý do nên tránh
$_REQUEST là $_GET và $_POST gộp thành một mảng. Các tệp php.ini đi kèm PHP đặt request_order = "GP", nên khi cả hai có cùng một khóa, POST thắng; không có thiết lập đó, cookie cũng bị gộp vào:
<?php
// POST /save.php?id=1 with a form field id=2
echo $_GET['id']; // "1"
echo $_POST['id']; // "2"
echo $_REQUEST['id']; // "2"
Trông thì tiện, nhưng nó che giấu nguồn gốc của giá trị. Một đoạn xử lý xóa bản ghi dựa trên $_REQUEST['id'] có thể bị kích hoạt bởi một liên kết đơn giản, đúng thứ mà các thao tác chỉ dùng POST muốn ngăn chặn. Hãy đọc $_GET hoặc $_POST theo đúng tên.
GET hay POST: nên dùng cái nào
| GET | POST | |
|---|---|---|
| Dữ liệu đi qua đâu | Trong URL: ?q=php&page=2 | Trong phần thân request |
| Đọc bằng | $_GET | $_POST |
| Bookmark, chia sẻ, nút quay lại | Có | Không (trình duyệt hỏi có gửi lại không) |
| Độ dài | Giới hạn bởi URL (vài nghìn ký tự là an toàn) | Giới hạn bởi post_max_size (mặc định 8M) |
| Tải tệp lên | Không | Có, với enctype="multipart/form-data" (đọc $_FILES) |
| Dùng cho | Tìm kiếm, bộ lọc, sắp xếp, phân trang | Đăng nhập, đăng ký, lưu, xóa, thanh toán |
Quy tắc quan trọng nhất: một request GET không được thay đổi bất cứ thứ gì. Trình duyệt tải trước liên kết, crawler đi theo liên kết, và mọi người chia sẻ liên kết, nên một liên kết ?delete=5 sớm muộn cũng sẽ bị một thứ không hề có ý định xóa đi theo. Bản thân không phương thức nào được mã hóa: HTTPS bảo vệ cả hai, còn POST chỉ giữ dữ liệu khỏi URL, lịch sử trình duyệt và log của máy chủ.
Câu hỏi thường gặp
Làm sao lấy một tham số từ URL trong PHP?
Đọc nó từ $_GET kèm giá trị mặc định: với page.php?id=42, $id = $_GET['id'] ?? null; cho bạn chuỗi "42". Mọi giá trị đều là chuỗi (hoặc mảng với id[]=), nên hãy chuyển kiểu và kiểm tra, ví dụ bằng filter_var($id, FILTER_VALIDATE_INT).
$_GET và $_POST khác nhau thế nào?
$_GET đến từ query string của URL, nên nhìn thấy được, lưu bookmark được và bị giới hạn độ dài; hãy dùng nó cho tìm kiếm, bộ lọc và phân trang. $_POST đến từ phần thân request của form gửi bằng method="post"; hãy dùng nó cho mọi thứ làm thay đổi dữ liệu, như lưu, mua hàng hay đăng nhập.
Làm sao kiểm tra một tham số GET có tồn tại trong PHP?
Dùng isset($_GET['q']), trả về false khi khóa không có hoặc là null. Để coi cả giá trị rỗng (?q=) là không có, hãy so sánh giá trị đã trim: trim($_GET['q'] ?? '') !== ''.
Có nên dùng $_REQUEST trong PHP không?
Thường là không. $_REQUEST gộp $_GET và $_POST (và tùy theo request_order, cả cookie), nên bạn không biết giá trị đến từ đâu, và một liên kết có thể cung cấp giá trị mà bạn tưởng đến từ form. Hãy đọc rõ ràng $_GET hoặc $_POST.
Làm sao biết một request là GET hay POST trong PHP?
So sánh $_SERVER['REQUEST_METHOD']: if ($_SERVER['REQUEST_METHOD'] === 'POST') { ... }. Cách này đáng tin cậy hơn isset($_POST['submit']), vốn thất bại khi nút không có name hoặc khi form được gửi bằng JavaScript hay một script khác không có trường đó.