Александр Некрасов · Автономное руководство

PHP: полный мануал с примерами, функциями и ООП

Разделы этой страницы
  1. URL: ссылки, query, Base64 и метаданные HTTP
  2. Поиск «C++ tea» не должен превращаться в другие параметры
  3. Что именно преобразуется: адрес, параметр, HTML или байты
  4. Все десять констант официальной категории
  5. Декодирование не является проверкой безопасности или схемы
  6. Стоимость, сеть и границы учебных примеров
  7. Практика: название товара с плюсом, слешем и амперсандом
  8. Полный указатель функций URL
  9. Функции и методы этой темы
  10. Код и руководство с собой
PHP 8.5.11149 глав4458 карточек справочника
Дерево руководства

Глава 93 · От основ к практике

URL: ссылки, query, Base64 и метаданные HTTP

Полные контракты URL-функций с постепенными примерами: что кодируется, что проверяется, где уже снят слой кодирования.

Поиск «C++ tea» не должен превращаться в другие параметры

Наглядная модель

Знак + остаётся частью поискового запроса

Пользователь ищет C++ tea. Название должно пройти через URL и восстановиться без изменения.

  1. q = C++ tea

    Два плюса и пробел относятся к данным пользователя.

  2. http_build_query

    Плюсы превращаются в %2B, пробел при RFC3986 — в %20.

  3. q=C%2B%2B%20tea

    Query помещается после ? в известный маршрут /search.

  4. Приём PHP

    $_GET['q'] уже содержит C++ tea. Лишний urldecode испортил бы плюсы.

Query-кодирование и HTML-экранирование — разные этапы. Перед вставкой готового адреса в href экранируют весь атрибут.

Посетитель вводит название товара, а сайт строит ссылку на результаты. Введённый плюс, амперсанд или знак вопроса должен остаться частью названия, а не стать разделителем URL. Эта категория помогает собрать адрес, разобрать старый формат, перенести бинарные данные текстом и получить определённые метаданные HTTP/HTML.

Имя функции со скобками означает вызов: данные внутри скобок — аргументы, а результат можно сохранить через = в переменную с $. Строки записываются в кавычках; echo выводит текст, "\n" — перевод строки. Точка . склеивает строки. Массив ["q" => "чай"] хранит значение «чай» под ключом q. var_dump дополнительно показывает тип.

В проверках === false означает именно булев отказ, а не пустую строку или ноль. if выбирает действие по условию; throw new RuntimeException прекращает обычный путь при неожиданном отказе. foreach берёт элементы массива по очереди. Переменные, массивы и вызов и возврат функции можно повторить отдельно.

От пользовательского названия до понятной ссылки
  1. Значение q: C++ tea
  2. http_build_query кодирует именно значение
  3. /search?q=C%2B%2B%20tea&page=2
  4. PHP на принимающей стороне видит q как C++ tea
Собрать ссылку на вторую страницу поискаСамостоятельный пример
<?php
declare(strict_types=1);

$query = http_build_query(['q' => 'C++ tea', 'page' => 2], '', '&', PHP_QUERY_RFC3986);
$url = '/search?' . $query;
echo $url, "\n";
Ожидаемый результат
/search?q=C%2B%2B%20tea&page=2

Число 2 здесь становится текстом в query. При приёме формы/параметров его снова проверяют как допустимый номер страницы, а не считают автоматически доверенным целым.

Сетевых запросов в этом примере нет: создаётся только строка. Как HTML-поля попадают в PHP показывает принимающую сторону, а проверка внешних значений — различие формата и допустимости.

Что именно преобразуется: адрес, параметр, HTML или байты

Одна ссылка, два разных уровня
  1. Сначала значения → query с %HH
  2. Затем полный готовый URL
  3. Перед HTML-атрибутом — htmlspecialchars
  4. Браузер получает правильное значение href
ЗадачаИнструмент и граница
Несколько параметров запросаhttp_build_query строит query без ?. Не сохраняет все типы PHP.
Один сегмент путиrawurlencode кодирует компонент; разделяющие сегменты / добавляют отдельно.
Одно значение form-urlencodedurlencode использует + для пробела.
Разобрать старый URLparse_url выделяет части, но не валидирует адрес. Для PHP8.5+ есть стандартные URI-классы.
Бинарный набор в текстовом APIbase64_encode и base64_decode по договору формата. Это не шифрование.
Получить HTTP-заголовкиget_headers выполняет запрос: нужны сеть, timeout и политика адресов.
Именованные meta из HTMLget_meta_tags читает файл до , не выполняет JavaScript.
Правильно разместить готовый URL в HTML-атрибутеСамостоятельный пример
<?php
declare(strict_types=1);

$url = '/search?' . http_build_query(['q' => 'tea & cake', 'page' => 2], '', '&', PHP_QUERY_RFC3986);
echo '<a href="' . htmlspecialchars($url, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') . '">Search</a>', "\n";
Ожидаемый результат
<a href="/search?q=tea%20%26%20cake&amp;page=2">Search</a>

%26 внутри q и & между HTML-параметрами выполняют разные задачи. Не храните заранее HTML-экранированный URL как адрес HTTP-клиента.

Все десять констант официальной категории

Константа — именованная настройка. Её имя пишется без $ и без кавычек. Восемь PHP_URL_* выбирают компонент parse_url, две PHP_QUERY_* — представление параметров в http_build_query.

Выбор одного компонента
  1. Адрес содержит :8443
  2. PHP_URL_PORT выбирает порт
  3. parse_url возвращает int 8443
  4. Отсутствующий порт дал бы null
КонстантаЧто выбирает / результат
PHP_URL_SCHEMEСхема, например https; строка
PHP_URL_HOSTИмя узла; строка
PHP_URL_PORTПорт; int, не строка
PHP_URL_USERПользователь из userinfo; строка, не подтверждённая авторизация
PHP_URL_PASSПароль из userinfo; не выводить в журнал
PHP_URL_PATHПуть с сохранёнными %HH
PHP_URL_QUERYЧасть после ?, без самого ?
PHP_URL_FRAGMENTЧасть после #, без #
PHP_QUERY_RFC1738Form-urlencoded: пробел кодируется +
PHP_QUERY_RFC3986Пробел кодируется %20; полезно для согласованной RFC3986 query

Отсутствующие выбранные компоненты дают null; parse_url с серьёзно неверным адресом может вернуть false. Без выбора компонента вернётся массив только найденных частей. С PHP 8.0 пустые query/fragment отличаются от отсутствующих.

Декодирование не является проверкой безопасности или схемы

Приложение должно знать, какой слой уже снял веб-сервер/PHP. В $_GET и обычном $_POST значения уже разобраны по правилам формы. Повторный urldecode может заменить настоящий плюс пробелом, а второй rawurldecode — превратить закодированный %2F в разделитель пути.

Типичная ошибка двойного декодирования
  1. Передали буквальный текст A%2FB
  2. В запросе он записан A%252FB
  3. PHP уже восстановил A%2FB
  4. Лишний декодер делает A/B — уже другое значение
Показать, как повторный urldecode меняет значениеСамостоятельный пример
<?php
declare(strict_types=1);

parse_str('q=C%2B%2B', $received);
echo $received['q'], "\n";
echo '[' . urldecode($received['q']) . "]\n";
Ожидаемый результат
C++
[C  ]

parse_str моделирует разбор query. На реальном запросе PHP выполняет этот этап до обращения к $_GET. Сначала определяют формат и число слоёв, затем проверяют значение.

Percent/Base64 не проверяют полномочия, допустимость пути, HTML-контекст или назначение HTTP-запроса. Для ссылки «вернуться после входа» обычно выбирают разрешённый локальный маршрут; произвольный внешний redirect нуждается в отдельной политике. Парсер и сетевой клиент должны одинаково понимать адрес, включая редиректы и Unicode.

В PHP 8.5 доступны Uri\Rfc3986\Uri и Uri\WhatWg\Url. Выбор стандарта связан с задачей: серверная URI-обработка и браузерные URL могут иметь разные правила. Новую разработку не следует строить на случайных эвристиках parse_url.

Стоимость, сеть и границы учебных примеров

Разделяем локальную и сетевую работу
  1. Кодирование строки работает с памятью процесса
  2. Размер результата зависит от входа и формата
  3. get_headers/get_meta_tags(URL) добавляют сеть и ожидание
  4. Ограничения размера/времени задаёт приложение

Base64 увеличивает объём примерно на треть, percent-encoding может потребовать три ASCII-байта на один исходный байт. Большие вложенные массивы дают длинную query, которую могут ограничить браузер, прокси или сервер. Для больших данных обычно выбирают тело запроса и согласованный JSON/multipart, а не бесконечную ссылку.

get_headers на каждом показе карточки сайта создаёт дополнительную зависимость от сети. Кэшируйте нужные метаданные по правилам продукта и обрабатывайте недоступность источника. Полученный HTTP200 подтверждает ответ endpoint, а не корректность всех функций сервиса.

Примеры get_headers требуют локального HTTP fixture и отдельно проверены через него. Обычная проверка PHP-синтаксиса без сервера не выдаётся за сетевой тест. Локальные get_meta_tags читают приложенные HTML-файлы; это не проверка произвольного сайта, HTML5-парсинга или браузерного JavaScript.

Практика: название товара с плюсом, слешем и амперсандом

Соберите ссылку на поиск A/B + tea & cake с фильтром available=true. Сначала получите query, затем HTML-ссылку, а получатель должен увидеть исходную строку целиком. Не кодируйте весь URL, не удаляйте специальные символы и не используйте повторный urldecode.

Критерий результата
  1. Исходное q не изменилось
  2. available передан как 1
  3. HTML-атрибут экранирован отдельно
  4. При разборе q восстановлен точно
Решение с проверкой пути туда и обратноСамостоятельный пример
<?php
declare(strict_types=1);

$original = 'A/B + tea & cake';
$query = http_build_query(['q' => $original, 'available' => true], '', '&', PHP_QUERY_RFC3986);
echo $query, "\n";
parse_str($query, $received);
var_dump($received['q'] === $original, $received['available'] === '1');
Ожидаемый результат
q=A%2FB%20%2B%20tea%20%26%20cake&available=1
bool(true)
bool(true)

Принимающая сторона получила текст "1", а не PHP bool. Далее проверяют, допустим ли такой фильтр, и используют подготовленные параметры запроса к базе. Следующий шаг — работа с базой.

Полный указатель функций URL

ФункцияНазначение
base64_decodeВосстановить байты из Base64 и явно отличить ошибку от пустого результата.
base64_encodeПередать произвольные байты в текстовом поле по договору Base64.
get_headersПолучить HTTP-заголовки ответа собственного известного endpoint и отдельно оценить статус.
get_meta_tagsПрочитать именованные meta-теги из HTML-файла, например описание страницы своего каталога.
http_build_queryПревратить набор параметров в query-строку, не собирая вручную амперсанды и escape-последовательности.
parse_urlРазобрать совместимый старый URL-код на компоненты, не принимая разбор за валидацию адреса.
rawurldecodeРаскодировать %HH, оставив знак + обычным плюсом.
rawurlencodeЗакодировать один сегмент пути или компонент по RFC 3986.
urldecodeРаскодировать значение формы/query: %HH в байты, + в пробел.
urlencodeЗакодировать одно значение формы/query по application/x-www-form-urlencoded.

Функции и методы этой темы

Откройте карточку, чтобы увидеть договор функции, примеры, ограничения и связанные инструменты.

base64_encodeПередать произвольные байты в текстовом поле по договору Base64.

PHP 8.2+ · standard

base64_encode(string $string): string

Передать произвольные байты в текстовом поле по договору Base64.

Имя функции со скобками означает вызов: данные внутри скобок — аргументы, а результат можно сохранить через = в переменную с $. Строки записываются в кавычках; echo выводит текст, "\n" — перевод строки. Точка . склеивает строки. Массив ["q" => "чай"] хранит значение «чай» под ключом q. var_dump дополнительно показывает тип.

В проверках === false означает именно булев отказ, а не пустую строку или ноль. if выбирает действие по условию; throw new RuntimeException прекращает обычный путь при неожиданном отказе. foreach берёт элементы массива по очереди. Переменные, массивы и вызов и возврат функции можно повторить отдельно.

Часть вызоваЗначение
stringИсходная строка байтов: может быть текстом UTF-8 или бинарным содержимым с NUL.
ВозвратСтрока стандартного Base64: буквы, цифры, +, / и возможное завершающее =. Она примерно на треть длиннее входа: 4 × ceil(N/3).
ГраницыКодирование обратимо без ключа: не скрывает пароли и не подтверждает подлинность. Это не Base64url и не автоматическое URL-кодирование.
Байты в текстовый конверт
  1. Байты PHP
  2. Группы по три байта превращаются в четыре символа
  3. Результат UEhQ можно поместить в текстовое поле
  4. Получатель декодирует обратно ровно PHP
Упаковать короткий текст в Base64Самостоятельный пример
<?php
declare(strict_types=1);

$encoded = base64_encode('PHP');
echo $encoded, "\n";
echo base64_decode($encoded, true), "\n";
Ожидаемый результат
UEhQ
PHP

Упаковка видима, но не секретна. Любой получатель строки UEhQ может восстановить исходный текст.

Передать нулевой байт без потери данныхСамостоятельный пример
<?php
declare(strict_types=1);

$bytes = "A\0B";
$encoded = base64_encode($bytes);
echo $encoded, "\n";
echo bin2hex(base64_decode($encoded, true)), "\n";
echo http_build_query(['data' => $encoded], '', '&', PHP_QUERY_RFC3986), "\n";
Ожидаемый результат
QQBC
410042
data=QQBC

bin2hex делает бинарный результат наблюдаемым. В URL Base64 всё равно помещают через построитель query: другие данные могут дать +, / и =.

Не потерять + и / при переносе через queryСамостоятельный пример
<?php
declare(strict_types=1);

$encoded = base64_encode(hex2bin('fbff'));
echo $encoded, "\n";
$query = http_build_query(['blob' => $encoded], '', '&', PHP_QUERY_RFC3986);
echo $query, "\n";
parse_str($query, $received);
var_dump($received['blob'] === $encoded);
Ожидаемый результат
+/8=
blob=%2B%2F8%3D
bool(true)

hex2bin превращает известную шестнадцатеричную запись в байты. parse_str здесь моделирует декодирование query PHP. Base64url использует - и _ вместо + и /, а правило padding задаётся протоколом; это отдельный вариант.

Для большого файла полное чтение плюс Base64-копия увеличивают память. Если API принимает бинарный upload/multipart или поток — лишняя Base64-упаковка может не требоваться. Не вставляйте декодированный HTML без экранирования: смена представления не делает содержимое доверенным.

Связанные инструменты: base64_decode; http_build_query; urlencode.

base64_decodeВосстановить байты из Base64 и явно отличить ошибку от пустого результата.

PHP 8.2+ · standard

base64_decode(string $string, bool $strict = false): string|false

Восстановить байты из Base64 и явно отличить ошибку от пустого результата.

Имя функции со скобками означает вызов: данные внутри скобок — аргументы, а результат можно сохранить через = в переменную с $. Строки записываются в кавычках; echo выводит текст, "\n" — перевод строки. Точка . склеивает строки. Массив ["q" => "чай"] хранит значение «чай» под ключом q. var_dump дополнительно показывает тип.

В проверках === false означает именно булев отказ, а не пустую строку или ноль. if выбирает действие по условию; throw new RuntimeException прекращает обычный путь при неожиданном отказе. foreach берёт элементы массива по очереди. Переменные, массивы и вызов и возврат функции можно повторить отдельно.

Часть вызоваЗначение
stringТекст стандартного Base64, не автоматически Base64url или data: URL целиком.
strictПо умолчанию посторонние символы отбрасываются. true включает проверку недопустимых символов/формата, но не проверяет бизнес-схему, криптографическую подлинность или каноничность представления.
ВозвратИсходные байты как строка либо false при отказе. Пустая строка допустима; результат может содержать NUL и не быть UTF-8.
Проверяем конверт перед чтением содержимого
  1. Пришёл UEhQ
  2. base64_decode(..., true) разбирает Base64
  3. Получена строка PHP либо false
  4. Отдельно проверяются размер и смысл восстановленных данных
Декодировать известное корректное значениеСамостоятельный пример
<?php
declare(strict_types=1);

$decoded = base64_decode('UEhQ', true);
if ($decoded === false) { throw new RuntimeException('Invalid Base64'); }
echo $decoded, "\n";
var_dump(base64_decode('', true));
Ожидаемый результат
PHP
string(0) ""

Пустой корректный конверт возвращает пустую строку. Проверка if (!$decoded) спутала бы её с отказом.

Не молча отбрасывать мусор во входеСамостоятельный пример
<?php
declare(strict_types=1);

var_dump(base64_decode('UE!hQ'));
var_dump(base64_decode('UE!hQ', true));
Ожидаемый результат
string(3) "PHP"
bool(false)

Без strict восклицательный знак исчез. В интеграции такие потери могут скрыть повреждение сообщения; сначала согласуйте допустимый формат.

Если договор требует единственное каноническое представлениеСамостоятельный пример
<?php
declare(strict_types=1);

foreach (['QQ==', 'QR==', 'QQ'] as $text) {
    $bytes = base64_decode($text, true);
    $canonical = $bytes !== false && base64_encode($bytes) === $text;
    echo $text, ': ', $canonical ? 'canonical' : 'different representation', "\n";
}
Ожидаемый результат
QQ==: canonical
QR==: different representation
QQ: different representation

В PHP 8.5 strict ещё принимает эти неканонические варианты. Сравнение обратного кодирования дополнительно требует стандартный алфавит, padding и точную запись. Для протокола без padding/с разрешёнными пробелами нужна именно его политика, а не этот критерий.

Прежде чем декодировать огромный внешний ввод, ограничьте длину кодированной строки, затем размер восстановленного содержимого. Не «исправляйте» неизвестный Base64 заменой всех пробелов на +: это может скрыть ошибку переноса через форму. Исправьте кодирование на стороне отправителя.

Связанные инструменты: base64_encode; http_build_query; urldecode.

urlencodeЗакодировать одно значение формы/query по application/x-www-form-urlencoded.

PHP 8.2+ · standard

urlencode(string $string): string

Закодировать одно значение формы/query по application/x-www-form-urlencoded.

Имя функции со скобками означает вызов: данные внутри скобок — аргументы, а результат можно сохранить через = в переменную с $. Строки записываются в кавычках; echo выводит текст, "\n" — перевод строки. Точка . склеивает строки. Массив ["q" => "чай"] хранит значение «чай» под ключом q. var_dump дополнительно показывает тип.

В проверках === false означает именно булев отказ, а не пустую строку или ноль. if выбирает действие по условию; throw new RuntimeException прекращает обычный путь при неожиданном отказе. foreach берёт элементы массива по очереди. Переменные, массивы и вызов и возврат функции можно повторить отдельно.

Часть вызоваЗначение
stringОтдельный компонент, а не весь адрес со схемой, слешами, ? и #.
ВозвратБайты кроме ASCII-букв/цифр и -_. заменяются %HH. Пробел становится +, настоящий плюс %2B; ~ кодируется как %7E.
КодировкаФункция кодирует существующие байты, не переводит текст из одной кодировки в другую. Для Unicode заранее согласуйте UTF-8.
ГраницаНе защищает HTML-атрибут сам по себе и не проверяет схему/домен URL. Повторное кодирование превратит % в %25.
Различаем данные и разделитель
  1. Текст tea + cake содержит пробелы и плюс
  2. Пробелы получают +
  3. Настоящий плюс получает %2B
  4. Получатель восстанавливает данные по тому же договору
Кодировать пробел и настоящий плюсСамостоятельный пример
<?php
declare(strict_types=1);

echo urlencode('tea + cake'), "\n";
echo urldecode(urlencode('tea + cake')), "\n";
Ожидаемый результат
tea+%2B+cake
tea + cake

Разница между пробелом и знаком + сохраняется. Это не замена пробелов дефисами для красивого slug.

Собрать небольшую ссылку поискаСамостоятельный пример
<?php
declare(strict_types=1);

$query = 'C++ tea';
$url = '/search?q=' . urlencode($query);
echo $url, "\n";
echo htmlspecialchars($url, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'), "\n";
Ожидаемый результат
/search?q=C%2B%2B+tea
/search?q=C%2B%2B+tea

Для нескольких параметров предпочтительнее http_build_query. Перед вставкой готового адреса в HTML выполняется отдельное HTML-экранирование; оно не заменяет кодирование параметра.

Не кодировать готовые escape-последовательности ещё разСамостоятельный пример
<?php
declare(strict_types=1);

$once = urlencode('A/B');
echo $once, "\n";
echo urlencode($once), "\n";
Ожидаемый результат
A%2FB
A%252FB

Вторая строка описывает буквальный текст A%2FB. Повторное кодирование не «усиливает защиту», а меняет значение.

Связанные инструменты: urldecode; http_build_query; rawurlencode.

rawurlencodeЗакодировать один сегмент пути или компонент по RFC 3986.

PHP 8.2+ · standard

rawurlencode(string $string): string

Закодировать один сегмент пути или компонент по RFC 3986.

Имя функции со скобками означает вызов: данные внутри скобок — аргументы, а результат можно сохранить через = в переменную с $. Строки записываются в кавычках; echo выводит текст, "\n" — перевод строки. Точка . склеивает строки. Массив ["q" => "чай"] хранит значение «чай» под ключом q. var_dump дополнительно показывает тип.

В проверках === false означает именно булев отказ, а не пустую строку или ноль. if выбирает действие по условию; throw new RuntimeException прекращает обычный путь при неожиданном отказе. foreach берёт элементы массива по очереди. Переменные, массивы и вызов и возврат функции можно повторить отдельно.

Часть вызоваЗначение
stringОтдельный компонент, а не весь адрес со схемой, слешами, ? и #.
ВозвратБайты кроме ASCII-букв/цифр и -_.~ заменяются %HH. Пробел становится %20, настоящий плюс %2B.
КодировкаФункция кодирует существующие байты, не переводит текст из одной кодировки в другую. Для Unicode заранее согласуйте UTF-8.
ГраницаНе защищает HTML-атрибут сам по себе и не проверяет схему/домен URL. Повторное кодирование превратит % в %25.
Различаем данные и разделитель
  1. Текст tea + cake содержит пробелы и плюс
  2. Пробелы получают %20
  3. Настоящий плюс получает %2B
  4. Получатель восстанавливает данные по тому же договору
Кодировать пробел и настоящий плюсСамостоятельный пример
<?php
declare(strict_types=1);

echo rawurlencode('tea + cake'), "\n";
echo rawurldecode(rawurlencode('tea + cake')), "\n";
Ожидаемый результат
tea%20%2B%20cake
tea + cake

Разница между пробелом и знаком + сохраняется. Это не замена пробелов дефисами для красивого slug.

Собрать путь из двух отдельных сегментовСамостоятельный пример
<?php
declare(strict_types=1);

$category = rawurlencode('tea sets');
$product = rawurlencode('A/B');
echo '/catalog/' . $category . '/' . $product, "\n";
Ожидаемый результат
/catalog/tea%20sets/A%2FB

Слеш внутри A/B закодирован как часть одного сегмента. Но веб-сервер/роутер могут отдельно обрабатывать %2F: допустимость таких идентификаторов задаётся маршрутом. Не кодируйте всю строку https://… одной функцией.

Не кодировать готовые escape-последовательности ещё разСамостоятельный пример
<?php
declare(strict_types=1);

$once = rawurlencode('A/B');
echo $once, "\n";
echo rawurlencode($once), "\n";
Ожидаемый результат
A%2FB
A%252FB

Вторая строка описывает буквальный текст A%2FB. Повторное кодирование не «усиливает защиту», а меняет значение.

Связанные инструменты: rawurldecode; http_build_query; urlencode.

urldecodeРаскодировать значение формы/query: %HH в байты, + в пробел.

PHP 8.2+ · standard

urldecode(string $string): string

Раскодировать значение формы/query: %HH в байты, + в пробел.

Имя функции со скобками означает вызов: данные внутри скобок — аргументы, а результат можно сохранить через = в переменную с $. Строки записываются в кавычках; echo выводит текст, "\n" — перевод строки. Точка . склеивает строки. Массив ["q" => "чай"] хранит значение «чай» под ключом q. var_dump дополнительно показывает тип.

В проверках === false означает именно булев отказ, а не пустую строку или ноль. if выбирает действие по условию; throw new RuntimeException прекращает обычный путь при неожиданном отказе. foreach берёт элементы массива по очереди. Переменные, массивы и вызов и возврат функции можно повторить отдельно.

Часть вызоваЗначение
stringОдин ещё закодированный компонент, не весь URL перед разделением.
ВозвратСтрока с раскодированными %HH и пробелами вместо +.
Неправильный вводНеполные/неhex последовательности % не являются строгой ошибкой: обычно остаются как текст. Результат может содержать NUL/невалидный UTF-8.
СуперглобальныеPHP уже раскодировал query в $_GET и обычное form-urlencoded тело в $_POST. Повторный вызов часто портит исходное значение.
Один слой кодирования
  1. Пришло tea+cake%20%2B%20milk
  2. %20 превращается в пробел, %2B в плюс
  3. Исходный + превращается в пробел
  4. Результат ещё требует проверки назначения
Посмотреть различие плюса и процентаСамостоятельный пример
<?php
declare(strict_types=1);

echo urldecode('tea+cake%20%2B%20milk'), "\n";
Ожидаемый результат
tea cake + milk

Декодер выбирают по формату отправителя. Query формы и сегмент пути могут использовать разные правила.

Раскодировать ровно один слойСамостоятельный пример
<?php
declare(strict_types=1);

$once = urldecode('A%252FB');
echo $once, "\n";
echo urldecode($once), "\n";
echo urldecode('%ZZ%2'), "\n";
Ожидаемый результат
A%2FB
A/B
%ZZ%2

После второго вызова появляется новый разделитель /. Нельзя сначала проверять путь, а затем раскодировать его ещё раз и использовать уже изменившееся значение.

Увидеть бинарный байт после декодированияСамостоятельный пример
<?php
declare(strict_types=1);

echo bin2hex(urldecode('A%00B')), "\n";
Ожидаемый результат
410042

Декодирование — преобразование, не очистка. Для файловых путей нулевой байт недопустим; для HTML всё равно требуется htmlspecialchars.

Связанные инструменты: urlencode; parse_url; http_build_query.

rawurldecodeРаскодировать %HH, оставив знак + обычным плюсом.

PHP 8.2+ · standard

rawurldecode(string $string): string

Раскодировать %HH, оставив знак + обычным плюсом.

Имя функции со скобками означает вызов: данные внутри скобок — аргументы, а результат можно сохранить через = в переменную с $. Строки записываются в кавычках; echo выводит текст, "\n" — перевод строки. Точка . склеивает строки. Массив ["q" => "чай"] хранит значение «чай» под ключом q. var_dump дополнительно показывает тип.

В проверках === false означает именно булев отказ, а не пустую строку или ноль. if выбирает действие по условию; throw new RuntimeException прекращает обычный путь при неожиданном отказе. foreach берёт элементы массива по очереди. Переменные, массивы и вызов и возврат функции можно повторить отдельно.

Часть вызоваЗначение
stringОдин ещё закодированный компонент, не весь URL перед разделением.
ВозвратСтрока с раскодированными %HH. Знак + остаётся +.
Неправильный вводНеполные/неhex последовательности % не являются строгой ошибкой: обычно остаются как текст. Результат может содержать NUL/невалидный UTF-8.
СуперглобальныеPHP уже раскодировал query в $_GET и обычное form-urlencoded тело в $_POST. Повторный вызов часто портит исходное значение.
Один слой кодирования
  1. Пришло tea+cake%20%2B%20milk
  2. %20 превращается в пробел, %2B в плюс
  3. Исходный + сохраняется
  4. Результат ещё требует проверки назначения
Посмотреть различие плюса и процентаСамостоятельный пример
<?php
declare(strict_types=1);

echo rawurldecode('tea+cake%20%2B%20milk'), "\n";
Ожидаемый результат
tea+cake + milk

Декодер выбирают по формату отправителя. Query формы и сегмент пути могут использовать разные правила.

Раскодировать ровно один слойСамостоятельный пример
<?php
declare(strict_types=1);

$once = rawurldecode('A%252FB');
echo $once, "\n";
echo rawurldecode($once), "\n";
echo rawurldecode('%ZZ%2'), "\n";
Ожидаемый результат
A%2FB
A/B
%ZZ%2

После второго вызова появляется новый разделитель /. Нельзя сначала проверять путь, а затем раскодировать его ещё раз и использовать уже изменившееся значение.

Увидеть бинарный байт после декодированияСамостоятельный пример
<?php
declare(strict_types=1);

echo bin2hex(rawurldecode('A%00B')), "\n";
Ожидаемый результат
410042

Декодирование — преобразование, не очистка. Для файловых путей нулевой байт недопустим; для HTML всё равно требуется htmlspecialchars.

Связанные инструменты: rawurlencode; parse_url; http_build_query.

http_build_queryПревратить набор параметров в query-строку, не собирая вручную амперсанды и escape-последовательности.

PHP 8.2+ · standard

http_build_query(array|object $data, string $numeric_prefix = "", ?string $arg_separator = null, int $encoding_type = PHP_QUERY_RFC1738): string

Превратить набор параметров в query-строку, не собирая вручную амперсанды и escape-последовательности.

Имя функции со скобками означает вызов: данные внутри скобок — аргументы, а результат можно сохранить через = в переменную с $. Строки записываются в кавычках; echo выводит текст, "\n" — перевод строки. Точка . склеивает строки. Массив ["q" => "чай"] хранит значение «чай» под ключом q. var_dump дополнительно показывает тип.

В проверках === false означает именно булев отказ, а не пустую строку или ноль. if выбирает действие по условию; throw new RuntimeException прекращает обычный путь при неожиданном отказе. foreach берёт элементы массива по очереди. Переменные, массивы и вызов и возврат функции можно повторить отдельно.

Часть вызоваЗначение
dataМассив, включая вложенные массивы, либо объект с публичными свойствами. __toString не вызывается автоматически. null и пустые вложенные массивы не создают параметров; bool становится 1/0.
numeric_prefixПрефикс числовых ключей только верхнего уровня. Не переименовывает все вложенные индексы.
arg_separatorРазделитель параметров. null (с 8.0) берёт arg_separator.output; для сетевого URL здесь явно "&". HTML-экранирование делают позднее для всего атрибута.
encoding_typePHP_QUERY_RFC1738: пробел +. PHP_QUERY_RFC3986: пробел %20. Передавайте документированную константу.
ВозвратСтрока без начального ?. Это не полный URL и не произвольный JSON-сериализатор.
ВерсииС 8.4 BackedEnum внутри data преобразуется в скалярное backing value. Pure enum не имеет такого значения.
Массив превращается в строку запроса
  1. q содержит C++ tea
  2. page содержит число 2
  3. Построитель кодирует ключи и значения
  4. Получаем q=C%2B%2B%20tea&page=2
Построить два параметра поискаСамостоятельный пример
<?php
declare(strict_types=1);

$parameters = ['q' => 'C++ tea', 'page' => 2];
$query = http_build_query($parameters, '', '&', PHP_QUERY_RFC3986);
echo $query, "\n";
echo '/search?' . $query, "\n";
Ожидаемый результат
q=C%2B%2B%20tea&page=2
/search?q=C%2B%2B%20tea&page=2

Символ ? добавляет ваше приложение между известным путём и query. Амперсанд отделяет параметры, а не является частью q.

Передать фильтр и список метокСамостоятельный пример
<?php
declare(strict_types=1);

$parameters = ['filter' => ['stock' => true], 'tags' => ['tea', 'gift'], 0 => 'preview'];
echo http_build_query($parameters, 'flag_', '&', PHP_QUERY_RFC3986), "\n";
Ожидаемый результат
filter%5Bstock%5D=1&tags%5B0%5D=tea&tags%5B1%5D=gift&flag_0=preview

Квадратные скобки — соглашение PHP о вложенных query-параметрах. Другой API может требовать tags=tea&tags=gift или строку CSV: формат надо согласовать, а не считать универсальным.

Увидеть потерю типов и пропуск пустых структурСамостоятельный пример
<?php
declare(strict_types=1);

$parameters = ['missing' => null, 'list' => [], 'text' => '', 'enabled' => false, 'count' => 0];
$query = http_build_query($parameters, '', '&');
echo $query, "\n";
parse_str($query, $restored);
var_dump($restored['count']);
Ожидаемый результат
text=&enabled=0&count=0
string(1) "0"

Это не обратимый перенос PHP-массива: null/[] пропали, число стало текстом. Если API требует сохранить типы и пустые массивы, согласуйте JSON вместо query.

Явно выбрать представление объектаСамостоятельный пример
<?php
declare(strict_types=1);

class SearchLabel
{
    public string $label = 'gift';
    private string $internal = 'hidden';
    public function __toString(): string { return 'Gift selection'; }
}
$label = new SearchLabel();
echo http_build_query(['item' => $label], '', '&'), "\n";
echo http_build_query(['item' => (string) $label], '', '&'), "\n";
Ожидаемый результат
item%5Blabel%5D=gift
item=Gift+selection

Сначала передаётся публичное свойство. Явное (string) вызывает __toString, и тогда строится обычное строковое значение. Private не попадает в query, но это не повод передавать произвольный объект с потенциально секретными public-полями.

Передать значение BackedEnum в PHP 8.4+Самостоятельный пример
<?php
declare(strict_types=1);

enum ViewMode: string { case Compact = 'compact'; }
echo http_build_query(['view' => ViewMode::Compact], '', '&'), "\n";
Ожидаемый результат
view=compact

В более старом PHP поведение отличалось. Для совместимой явной записи используйте ViewMode::Compact->value. Сам enum объясняется в разделе перечислений.

Для подписанного URL порядок параметров, представление пробела, дубликаты ключей и формат чисел должны совпадать с договором подписи. http_build_query сам не сортирует канонически все данные по внешнему стандарту. Не передавайте в него уже urlencode-обработанные значения: получите %25 вместо прежнего %. Объекты и вложенность обходятся рекурсивно, поэтому большой массив создаёт большую строку.

Связанные инструменты: parse_url; urlencode; rawurlencode.

parse_urlРазобрать совместимый старый URL-код на компоненты, не принимая разбор за валидацию адреса.

PHP 8.2+ · standard

parse_url(string $url, int $component = -1): int|string|array|null|false

Разобрать совместимый старый URL-код на компоненты, не принимая разбор за валидацию адреса.

Имя функции со скобками означает вызов: данные внутри скобок — аргументы, а результат можно сохранить через = в переменную с $. Строки записываются в кавычках; echo выводит текст, "\n" — перевод строки. Точка . склеивает строки. Массив ["q" => "чай"] хранит значение «чай» под ключом q. var_dump дополнительно показывает тип.

В проверках === false означает именно булев отказ, а не пустую строку или ноль. if выбирает действие по условию; throw new RuntimeException прекращает обычный путь при неожиданном отказе. foreach берёт элементы массива по очереди. Переменные, массивы и вызов и возврат функции можно повторить отдельно.

Часть вызоваЗначение
urlСтрока адреса. Частичные и некорректные адреса тоже могут быть разобраны; функция не следует строго одному современному стандарту URL/URI.
componentОпустить/-1 — массив найденных частей. Либо одна из восьми PHP_URL_* констант в таблице ниже.
ВозвратМассив; выбранная строковая часть; целый port; null если выбранная часть отсутствует; false для серьёзно некорректного адреса. Неподдерживаемый component вызывает ValueError.
Декодирование%HH автоматически не раскодируется. Управляющие символы в частях могут заменяться _. Это не сохранение любого исходного ввода без изменений.
PHP 8.0Отсутствующий query/fragment отличается от присутствующего, но пустого: null против "".
Новый код PHP 8.5+Официальный мануал рекомендует Uri\Rfc3986\Uri или Uri\WhatWg\Url под соответствующий стандарт. Совместимость parse_url имеет смысл сохранять осознанно.
Разбор известного адреса
  1. https://shop.example:8443/products?q=tea#details
  2. scheme=https, host=shop.example, port=8443
  3. path=/products, query=q=tea
  4. fragment=details — отдельная часть, не параметр query
Получить конкретные части известного адресаСамостоятельный пример
<?php
declare(strict_types=1);

$url = 'https://shop.example:8443/products?q=tea#details';
echo parse_url($url, PHP_URL_HOST), "\n";
echo parse_url($url, PHP_URL_PATH), "\n";
echo parse_url($url, PHP_URL_QUERY), "\n";
var_dump(parse_url($url, PHP_URL_PORT));
Ожидаемый результат
shop.example
/products
q=tea
int(8443)

Домен .example в этом опыте — только строка: сетевой запрос не выполняется. Фрагмент после # браузер обычно использует локально; он не входит в HTTP request target.

Различить отсутствующую и пустую query-частьСамостоятельный пример
<?php
declare(strict_types=1);

var_dump(parse_url('https://shop.example/catalog', PHP_URL_QUERY));
var_dump(parse_url('https://shop.example/catalog?', PHP_URL_QUERY));
echo parse_url('/catalog/tea%20sets?q=A%2BB', PHP_URL_PATH), "\n";
Ожидаемый результат
NULL
string(0) ""
/catalog/tea%20sets

%20 остался в path. Не раскодируйте весь адрес до разделения: %2F, %3F и %23 могут стать новыми разделителями.

Убедиться, что успешный разбор не проверяет адресСамостоятельный пример
<?php
declare(strict_types=1);

$parts = parse_url('just some text');
echo $parts['path'], "\n";
var_dump(parse_url('https://shop.example:99999/'));
try { parse_url('https://shop.example/', 999); }
catch (ValueError $error) { echo "Unknown component\n"; }
Ожидаемый результат
just some text
bool(false)
Unknown component

Обычный текст принят как path. Это наглядная причина не считать parse_url проверкой разрешённой ссылки или безопасного назначения HTTP-запроса.

Отличить сетевой путь без схемы от обычного относительного путиСамостоятельный пример
<?php
declare(strict_types=1);

echo parse_url('//shop.example/catalog', PHP_URL_HOST), "\n";
var_dump(parse_url('shop.example/catalog', PHP_URL_HOST));
echo parse_url('file:///tmp/report.txt', PHP_URL_SCHEME), "\n";
Ожидаемый результат
shop.example
NULL
file

file:// имеет историческое специальное поведение. Пример только разбирает текст и не открывает файл. Относительные URL требуют корректного разрешения относительно базового адреса; ручная склейка не заменяет стандартный URL API.

Проверка host одним парсером перед сетевым запросом другим может быть небезопасной: они способны различно разобрать адрес. Для внешних URL нужны разрешённые схема/назначение, согласованный парсер и транспорт, контроль редиректов/DNS/сетевого доступа. Сам разбор не предотвращает SSRF. Безопасность веб-приложения и современное расширение URI.

Связанные инструменты: http_build_query; rawurldecode; get_headers.

get_meta_tagsПрочитать именованные meta-теги из HTML-файла, например описание страницы своего каталога.

PHP 8.2+ · standard

get_meta_tags(string $filename, bool $use_include_path = false): array|false

Прочитать именованные meta-теги из HTML-файла, например описание страницы своего каталога.

Имя функции со скобками означает вызов: данные внутри скобок — аргументы, а результат можно сохранить через = в переменную с $. Строки записываются в кавычках; echo выводит текст, "\n" — перевод строки. Точка . склеивает строки. Массив ["q" => "чай"] хранит значение «чай» под ключом q. var_dump дополнительно показывает тип.

В проверках === false означает именно булев отказ, а не пустую строку или ноль. if выбирает действие по условию; throw new RuntimeException прекращает обычный путь при неожиданном отказе. foreach берёт элементы массива по очереди. Переменные, массивы и вызов и возврат функции можно повторить отдельно.

Часть вызоваЗначение
filenameПуть к локальному HTML либо поддерживаемый URL. Чтение идёт построчно до закрывающего . URL открывается через stream wrapper и может создавать сетевой запрос.
use_include_pathtrue включает поиск локального файла по include_path. К URL эта настройка не относится.
ВозвратМассив: name становится ключом, content — значением. Имена приводятся к нижнему регистру, некоторые специальные символы заменяются _. При повторении имени сохраняется последний тег. false при невозможности открыть/прочитать источник.
Что не извлекаетсяНужен атрибут name. Open Graph с property, заголовок title и динамические DOM-изменения JavaScript не являются этой задачей. Это не полноценный современный HTML DOM-парсер.
БезопасностьЗначения остаются недоверенным текстом. Для показа в HTML требуется экранирование. Нельзя принимать произвольный URL/путь от посетителя: это чтение сервером и возможный SSRF.
HTML-тег превращается в элемент массива
  1. name выбирает ключ description
  2. content даёт значение Tea catalog
  3. После разбор прекращается
Получить описание из собственного HTMLСамостоятельный пример
<?php
declare(strict_types=1);

$tags = get_meta_tags(__DIR__ . '/page.html');
if ($tags === false) { throw new RuntimeException('Cannot read HTML'); }
echo $tags['description'] ?? 'No description', "\n";
Ожидаемый результат
Tea catalog

Оператор ?? выбирает запасной текст, если ключ отсутствует. Существование файла ещё не означает наличие meta description.

Проверить имена, дубликаты и границу headСамостоятельный пример
<?php
declare(strict_types=1);

$tags = get_meta_tags(__DIR__ . '/page.html');
echo $tags['description'], "\n", $tags['geo_position'], "\n";
var_dump(isset($tags['og:title']), isset($tags['late']));
Ожидаемый результат
Second
10;20
bool(false)
bool(false)

DESCRIPTION преобразован в description, второй тег перезаписал первый. geo.position стал geo_position. property не учитывается, как и тег после head.

Использовать include_path только для собственного локального файлаСамостоятельный пример
<?php
declare(strict_types=1);

$old = get_include_path();
try {
    set_include_path(__DIR__ . '/templates');
    $tags = get_meta_tags('page.html', true);
    if ($tags === false) { throw new RuntimeException('Cannot read template'); }
    echo $tags['author'], "\n";
} finally { set_include_path($old); }
Ожидаемый результат
Editorial team

Поиск разрешённого шаблона и восстановление настройки показаны явно. Не используйте include_path как механизм открытия произвольного файла по имени пользователя.

Отличить отказ чтения от страницы без теговСамостоятельный пример
<?php
declare(strict_types=1);

$warned = false;
set_error_handler(static function (int $level) use (&$warned): bool {
    if ($level !== E_WARNING) { return false; }
    $warned = true; return true;
});
try { $tags = get_meta_tags(__DIR__ . '/missing.html'); }
finally { restore_error_handler(); }
var_dump($tags === false, $warned);
Ожидаемый результат
bool(true)
bool(true)

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

У get_meta_tags нет параметра context. Изменение default stream context влияет на другие открытия в том же процессе; не прячьте такие глобальные эффекты в библиотечную функцию. Для контролируемого скачивания используйте HTTP-клиент с явными лимитами, затем полноценный HTML-парсер для нужных тегов. Даже построчное чтение может встретить огромную строку; сама функция не является лимитом размера.

Связанные инструменты: get_headers; parse_url; urlencode.

get_headersПолучить HTTP-заголовки ответа собственного известного endpoint и отдельно оценить статус.

PHP 8.2+ · standard

get_headers(string $url, bool $associative = false, ?resource $context = null): array|false

Получить HTTP-заголовки ответа собственного известного endpoint и отдельно оценить статус.

Имя функции со скобками означает вызов: данные внутри скобок — аргументы, а результат можно сохранить через = в переменную с $. Строки записываются в кавычках; echo выводит текст, "\n" — перевод строки. Точка . склеивает строки. Массив ["q" => "чай"] хранит значение «чай» под ключом q. var_dump дополнительно показывает тип.

В проверках === false означает именно булев отказ, а не пустую строку или ноль. if выбирает действие по условию; throw new RuntimeException прекращает обычный путь при неожиданном отказе. foreach берёт элементы массива по очереди. Переменные, массивы и вызов и возврат функции можно повторить отдельно.

Часть вызоваЗначение
urlHTTP-адрес назначения. Это реальный сетевой запрос сервера, а не разбор текста URL. Требуются доступный wrapper, настройки и права сети.
associativefalse — индексированный список строк, включая status lines. true — разобранные имена ключей; повторяющийся заголовок может стать массивом значений. С PHP 8.0 тип bool.
contextКонтекст от stream_context_create либо null для default context. Добавлен в PHP 7.1. В нём задают метод, timeout, redirect policy и другие параметры HTTP-wrapper.
МетодПо умолчанию GET, а не HEAD. HEAD явно задают через context; некоторые серверы обрабатывают HEAD иначе.
ВозвратМассив заголовков либо false при отказе. Массив сам по себе не означает 2xx; при редиректах может содержать несколько ответов.
ГраницаЗаголовки ответа отличаются от входящих заголовков запроса посетителя. Последние берут другими API/серверными переменными.
Запрос за метаданными
  1. PHP отправляет HEAD своему endpoint
  2. Сервер возвращает status line и заголовки
  3. get_headers получает список либо false
  4. Приложение проверяет статус и только нужные поля

Контекст — массив настроек транспорта, упакованный stream_context_create. Значение follow_location=0 запрещает автоматический переход в этих примерах. Переменная окружения PHP_MANUAL_HTTP_BASE указывает только на собственный учебный сервер на loopback. Эти примеры требуют запущенного HTTP fixture: отдельно от синтаксической проверки они проверены на настоящем локальном HTTP-ответе.

Получить status line через HEADПример для указанного окружения
<?php
declare(strict_types=1);

$base = getenv('PHP_MANUAL_HTTP_BASE');
if ($base === false || $base === '') { throw new RuntimeException('Start the local lesson HTTP fixture'); }
$context = stream_context_create(['http' => [
    'method' => 'HEAD', 'timeout' => 2, 'follow_location' => 0, 'ignore_errors' => true
]]);
$headers = get_headers($base . '/ok', false, $context);
if ($headers === false) { throw new RuntimeException('HTTP request failed'); }
echo $headers[0], "\n";
Ожидаемый результат
HTTP/1.1 200 OK

Статус фиксирован в нашем fixture. Внешний сервер может ответить другой версией HTTP или статусом. При выключенном follow_location первая status line относится именно к этому ответу.

Не считать повторяющийся заголовок одной строкойПример для указанного окружения
<?php
declare(strict_types=1);

$base = getenv('PHP_MANUAL_HTTP_BASE');
if ($base === false || $base === '') { throw new RuntimeException('Start the local lesson HTTP fixture'); }
$context = stream_context_create(['http' => [
    'method' => 'HEAD', 'timeout' => 2, 'follow_location' => 0
]]);
$headers = get_headers($base . '/repeat', true, $context);
if ($headers === false) { throw new RuntimeException('HTTP request failed'); }
$values = [];
foreach ($headers as $name => $value) {
    if (is_string($name) && strcasecmp($name, 'X-Lesson') === 0) {
        foreach ((array) $value as $item) { $values[] = $item; }
    }
}
echo implode(' | ', $values), "\n";
Ожидаемый результат
first | second

Имена HTTP-заголовков нечувствительны к регистру. Фиксированное обращение к headers["Content-Type"] не является универсальным регистронезависимым поиском. Для Set-Cookie повторения особенно существенны; их нельзя слепо склеивать в одно значение.

Увидеть редирект, не переходя по нему автоматическиПример для указанного окружения
<?php
declare(strict_types=1);

$base = getenv('PHP_MANUAL_HTTP_BASE');
if ($base === false || $base === '') { throw new RuntimeException('Start the local lesson HTTP fixture'); }
$context = stream_context_create(['http' => [
    'method' => 'HEAD', 'timeout' => 2, 'follow_location' => 0, 'ignore_errors' => true
]]);
$headers = get_headers($base . '/redirect', false, $context);
if ($headers === false) { throw new RuntimeException('HTTP request failed'); }
echo $headers[0], "\n";
echo in_array('Location: /ok', $headers, true) ? "Redirect observed\n" : "No location\n";
Ожидаемый результат
HTTP/1.1 302 Found
Redirect observed

Location в тесте имеет известный регистр. В общем случае ищут имена без учёта регистра, затем разрешают относительный адрес по стандарту и заново проверяют допустимость назначения. Нельзя считать первый 301/302 окончательным статусом после всей цепочки.

Полученный массив может описывать ошибку HTTPПример для указанного окружения
<?php
declare(strict_types=1);

$base = getenv('PHP_MANUAL_HTTP_BASE');
if ($base === false || $base === '') { throw new RuntimeException('Start the local lesson HTTP fixture'); }
$context = stream_context_create(['http' => [
    'method' => 'HEAD', 'timeout' => 2, 'follow_location' => 0, 'ignore_errors' => true
]]);
$headers = get_headers($base . '/missing', false, $context);
if ($headers === false) { throw new RuntimeException('Transport failure'); }
echo $headers[0], "\n";
Ожидаемый результат
HTTP/1.1 404 Not Found

Транспорт вернул ответ, но нужного ресурса нет. Не называйте любой непустой массив подтверждением доступности/исправности сайта.

timeout ограничивает операции чтения согласно wrapper, а не обещает полный deadline всей цепочки DNS/соединений/редиректов. Для контролируемого мониторинга/скачивания большого числа адресов обычно нужен HTTP-клиент с явной политикой ресурсов. Не выполняйте get_headers перед каждым последующим GET без необходимости: это дополнительный запрос, а ресурс между ними может измениться. TLS-проверку не отключают ради успешного ответа.

Связанные инструменты: parse_url; get_meta_tags; http_build_query.

Источники и обсуждения

Код и руководство с собой

Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.

Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.

Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.