Menu

PHP $_GET и $_POST: строка запроса и данные формы

$_GET хранит строку запроса URL (?page=2 даёт $_GET['page']), а $_POST хранит поля формы, отправленной с method="post". Как безопасно читать оба, строить ссылки через http_build_query, проверять $_SERVER['REQUEST_METHOD'] и выбирать между GET и POST.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

$_GET это массив из строки запроса URL, поэтому article.php?id=42&lang=en даёт $_GET['id'] === '42' и $_GET['lang'] === 'en'. $_POST это массив полей формы, отправленной с method="post". Читайте оба со значением по умолчанию, $_GET['id'] ?? null, потому что ключа нет всякий раз, когда нет параметра.

Запустите блок и нажимайте на ссылки: каждое нажатие снова запускает скрипт с $_GET, заполненным из строки запроса ссылки.

$_GET['lang'] содержит то, что написано в URL, а не только три выведенные вами ссылки. Любой может набрать ?lang=<script> в адресной строке, поэтому блок ищет значение в $languages, а не выводит его, и экранирует то единственное место, где выводит данные запроса.

Чтение числа из строки запроса

Каждое значение в $_GET это строка. Для номера страницы проверяйте и преобразуйте за один шаг через filter_var() и берите значение по умолчанию, когда значения нет, оно не число или вне диапазона. Пройдитесь по страницам, а потом попробуйте ссылки Page 999 и Page abc.

filter_var() возвращает целое 3 для "3" и значение опции default для любой другой строки, поэтому $page всегда пригодное целое число. Другие валидаторы перечислены на странице про filter_var.

Чтение данных формы через $_POST

Форма с method="post" отправляет поля в теле запроса, и PHP кладёт их в $_POST под атрибутом name каждого поля. $_SERVER['REQUEST_METHOD'] сообщает, это первый визит (GET) или отправка (POST). Заполните форму и нажмите Send, чтобы увидеть оба случая.

Пустое текстовое поле всё равно отправляется, как "", поэтому после отправки $_POST['title'] существует, даже если посетитель ничего не ввёл. На сервере REQUEST_METHOD задан всегда; ?? 'GET' лишь не даёт скрипту ругаться, когда вы запускаете файл через php в командной строке. Полный шаблон проверки и повторного вывода формы на странице о формах.

Форма поиска с method="get"

Используйте GET для формы, результатом которой должен быть URL, которым можно поделиться, например для поля поиска. Браузер превращает поля в строку запроса (?q=sort&level=beginner), а скрипт читает их из $_GET, ровно как со ссылкой. Поищите array или string.

Сборка ссылок через http_build_query

Ручная запись "?q=$q&page=2" ломается, как только в $q появляется пробел, & или #. http_build_query() кодирует каждое значение за вас, а результат проходит через htmlspecialchars(), когда попадает в href, потому что внутри HTML & должен быть &amp;.

parse_str() с двумя аргументами это то, как PHP строит $_GET из строки запроса, поэтому функция удобна для тестов. Всегда передавайте второй аргумент; старую форму с одним аргументом, которая создавала переменные, удалили в PHP 8.

$_REQUEST и почему его стоит избегать

$_REQUEST это $_GET и $_POST, объединённые в один массив. Файлы php.ini, которые поставляются с PHP, задают request_order = "GP", поэтому, когда оба содержат один ключ, побеждает POST; без этой настройки туда подмешиваются и cookie:

<?php
// POST /save.php?id=1 with a form field id=2
echo $_GET['id'];      // "1"
echo $_POST['id'];     // "2"
echo $_REQUEST['id'];  // "2"

Выглядит удобно, но скрывает, откуда пришло значение. Обработчик, который удаляет запись по $_REQUEST['id'], можно запустить обычной ссылкой, а именно от этого и должны защищать действия только через POST. Читайте $_GET или $_POST по имени.

GET или POST: что использовать

GETPOST
Где передаются данныеВ URL: ?q=php&page=2В теле запроса
Чем читать$_GET$_POST
Закладки, ссылки, кнопка назадДаНет (браузер спрашивает о повторной отправке)
ДлинаОграничена URL (несколько тысяч символов безопасно)Ограничена post_max_size (по умолчанию 8M)
Загрузка файловНетДа, с enctype="multipart/form-data" (читайте $_FILES)
Для чегоПоиск, фильтры, сортировка, пагинацияВход, регистрация, сохранение, удаление, платежи

Правило, которое важно: GET-запрос не должен ничего менять. Браузеры заранее загружают ссылки, краулеры по ним переходят, а люди ими делятся, поэтому по ссылке ?delete=5 рано или поздно перейдёт то, что не собиралось ничего удалять. Ни один из методов сам по себе не шифрует данные: оба защищает HTTPS, а POST лишь не пускает данные в URL, историю браузера и логи сервера.

Часто задаваемые вопросы

Как получить параметр из URL в PHP?

Прочитайте его из $_GET со значением по умолчанию: для page.php?id=42 $id = $_GET['id'] ?? null; даёт строку "42". Каждое значение это строка (или массив для id[]=), поэтому преобразуйте и проверьте его, например через filter_var($id, FILTER_VALIDATE_INT).

Чем $_GET отличается от $_POST?

$_GET берётся из строки запроса URL, поэтому он виден, сохраняется в закладках и ограничен по длине; используйте его для поиска, фильтров и страниц. $_POST берётся из тела запроса формы, отправленной с method="post"; используйте его для всего, что меняет данные: сохранение, покупка, вход.

Как проверить, есть ли GET-параметр, в PHP?

Используйте isset($_GET['q']), оно ложно, когда ключа нет или он равен null. Чтобы считать отсутствующим и пустое значение (?q=), сравнивайте значение после trim: trim($_GET['q'] ?? '') !== ''.

Стоит ли использовать $_REQUEST в PHP?

Обычно нет. $_REQUEST объединяет $_GET и $_POST (а в зависимости от request_order ещё и cookie), поэтому нельзя понять, откуда пришло значение, а ссылка может подставить значение, которое вы ждали из формы. Читайте $_GET или $_POST явно.

Как проверить, GET это запрос или POST, в PHP?

Сравните $_SERVER['REQUEST_METHOD']: if ($_SERVER['REQUEST_METHOD'] === 'POST') { ... }. Это надёжнее, чем isset($_POST['submit']), которое не срабатывает, когда у кнопки нет name или когда форму отправляет JavaScript или другой скрипт без этого поля.

Иллюстрация языков программирования Coddy

Учитесь программировать с Coddy

НАЧАТЬ