$_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 & должен быть &.
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: что использовать
| GET | POST | |
|---|---|---|
| Где передаются данные | В 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 или другой скрипт без этого поля.