Перейти к содержимому
Теория · PHP и веб · урок 2 из 7

$_GET, $_POST и формы

В ресторане заказ приходит на бланке. Посетитель вписывает в него блюдо, количество и пожелания. Бланк может прийти заполненным наполовину, совсем пустым или заполненным чужой рукой — повар узнает об этом, только когда прочитает его.

В PHP такие бланки — это данные запроса. Давайте посмотрим, где они лежат и чего от них ждать.

Параметры в адресе: $_GET

Адрес может нести данные. Параметры запроса — это всё, что стоит после ?: пары «имя=значение», разделённые знаком &. Для адреса /menu.php?page=3&city= PHP ещё до первой строки вашей программы кладёт параметры в массив $_GET.

$_GET — суперглобальный массив: PHP заполняет его сам, и он виден в любом месте программы, даже внутри функции.

В терминале запроса нет, поэтому в примерах первая строка изображает запрос: она сама присваивает $_GET. На встроенном сервере эту строку убирают, и массив заполняет PHP.

PHP
<?php

$_GET = ['page' => '3', 'city' => ''];
var_dump($_GET['page'] ?? 1); // string(1) "3"
var_dump($_GET['sort'] ?? 'name'); // string(4) "name"
var_dump($_GET['city'] ?? 'Paris'); // string(0) ""

Первая строка соответствует адресу ?page=3&city=. Параметр приходит в одном из трёх видов, и ?? ведёт себя в них по-разному.

Параметр есть

$_GET['page'] — строка '3', а не число. Значение параметра приходит строкой, даже если в нём одни цифры. Массивом оно приходит только у параметра с [] в имени, как в tags[]=a. ?? видит, что ключ есть и значение не null, и отдаёт '3'.

Параметра нет

Параметра sort в адресе не было, поэтому в $_GET нет такого ключа. Обычное чтение $_GET['sort'] дало бы предупреждение Warning: Undefined array key "sort". Как вы уже знаете, ?? сначала проверяет ключ и молча берёт значение справа — 'name'.

Параметр пустой

Запись city= передаёт ключ city с пустой строкой. Так же приходит поле формы, которое посетитель оставил пустым. ?? реагирует только на отсутствующий ключ и null, поэтому оставляет пустую строку и не подставляет 'Paris'.

Строка в число: (int)

Номер страницы нужен как число, поэтому значение приводят к int:

PHP
$_GET = ['page' => '3', 'size' => 'abc'];
$page = (int) ($_GET['page'] ?? 1);
$size = (int) ($_GET['size'] ?? 10);
var_dump($page); // int(3)
var_dump($size); // int(0)

Разберём по шагам:

  1. Скобки вокруг $_GET['page'] ?? 1 нужны, чтобы (int) применялся к результату ??.
  2. Строка '3' превращается в int(3).
  3. В size посетитель вписал abc, и (int) молча даёт 0.

Приведение делает из строки число, но не проверяет, разумное ли это число. Страница 0 или размер 0 — ошибка, о которой PHP не сообщит.

Формы и $_POST

Форма — это бланк заказа на самой странице. Когда посетитель нажимает кнопку формы с method="post", браузер отправляет значения полей не в адресе, а в теле запроса. PHP кладёт их в суперглобальный массив $_POST по именам из атрибута name.

PHP
<?php

$_SERVER['REQUEST_METHOD'] = 'POST';
$_POST = ['dish' => 'Soup', 'qty' => '2'];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $dish = $_POST['dish'] ?? '';
    $qty = (int) ($_POST['qty'] ?? 1);
    echo $qty, ' x ', $dish, "\n"; // 2 x Soup
}
?>
<form method="post">
    <input name="dish">
    <input name="qty">
    <button>Order</button>
</form>

Две строки после <?php изображают отправленную форму, остальное — настоящий шаблон:

  1. $_SERVER['REQUEST_METHOD'] хранит метод запроса: 'GET', когда страницу открыли по адресу, и 'POST', когда отправили такую форму.
  2. Если форму отправили, программа читает поля через ?? и приводит количество к числу.
  3. Ниже ?> стоит сама форма. Адреса у неё нет, поэтому браузер отправит её на ту же страницу.

Метод GET подходит для чтения: номер страницы, поиск, сортировка. Метод POST — для данных, которые что-то меняют: заказ, комментарий, регистрация.

Чем GET отличается от POST, часто спрашивают на собеседовании. Параметры GET видны в адресе и остаются в истории браузера, а поля POST идут в теле запроса.

Содержимое $_GET и $_POST задаёт посетитель. Он может стереть параметр, вписать ?page=abc или отправить форму с полями, которых на странице нет. В картинке с рестораном это бланк, заполненный чужой рукой, и доверять ему нельзя.

Только здесь картинка неточна: повар видит, кто отдал бланк, а программа не знает, кто прислал запрос. Отправить запрос можно и в обход вашей формы.

Частая ошибка

Параметр читают без ??:

PHP
<?php

$_GET = [];
$page = (int) $_GET['page']; // ✗
echo $page, "\n";
TEXT
Warning: Undefined array key "page"

Посетитель открыл адрес без ?page=, и ключа в $_GET нет. PHP выдаёт предупреждение и читает null, (int) null даёт 0, и программа печатает 0. Исправление — значение по умолчанию: $page = (int) ($_GET['page'] ?? 1);.

Главное

  • $_GET хранит параметры из адреса, $_POST — поля отправленной формы, и параметр без [] в имени приходит в них строкой.
  • Отсутствующий параметр — это отсутствующий ключ: $_GET['page'] ?? 1 даёт значение по умолчанию без предупреждения.
  • Пустой параметр city= — это ключ с пустой строкой, и ?? его не заменяет.
  • (int) превращает строку в число, но 'abc' молча становится 0: приведение — ещё не проверка.