Функция PHP header(): всё, что нужно знать
Функция header() в PHP позволяет отправлять HTTP-заголовки: перенаправлять пользователей, управлять кешированием и задавать коды статуса.
Каждый HTTP-ответ, отправляемый веб-сервером, состоит из двух частей: набора заголовков (метаданных — тип содержимого, правила кеширования, код статуса) и тела ответа (HTML, JSON, изображения или файла, которые получает браузер). Функция header() в PHP позволяет задавать эти заголовки прямо из скрипта — перенаправлять пользователей, отдавать файлы для загрузки, устанавливать тип содержимого, управлять кешированием и отправлять произвольные коды статуса.
В этом руководстве рассматривается синтаксис и параметры header(), главное правило, которое ставит всех в тупик (ошибка «headers already sent»), а также наиболее распространённые практические сценарии.
Что такое функция header()?
header() — это встроенная функция PHP, отправляющая необработанный HTTP-заголовок клиенту. Заголовок — это одна строка вида Content-Type: text/html или Location: /login, которую браузер читает до тела страницы. Поскольку заголовки передаются первыми, header() работает только пока PHP ещё формирует раздел заголовков — см. правило «headers already sent» ниже.
Синтаксис и параметры
header(string $header, bool $replace = true, int $response_code = 0): void| Параметр | Тип | Описание |
|---|---|---|
$header | string | Строка заголовка для отправки, например "Content-Type: application/json". |
$replace | bool | Заменяет ли этот вызов ранее отправленный заголовок с тем же именем. При значении false отправляются несколько заголовков с одинаковым именем. По умолчанию true. |
$response_code | int | Принудительно задаёт HTTP-код статуса ответа. 0 (по умолчанию) означает «оставить статус без изменений». |
Функция ничего не возвращает (void). Она не сообщает, был ли заголовок принят — если вывод уже был отправлен, вместо этого выдаётся предупреждение.
Установка заголовка
Простейший случай — объявить, какой тип содержимого возвращает ответ. Это необходимо, когда скрипт возвращает JSON, XML, простой текст или файл вместо HTML:
<?php
header("Content-Type: application/json");
echo json_encode(["status" => "ok", "id" => 42]);Заголовок Content-Type указывает браузеру обрабатывать тело как JSON, поэтому {"status":"ok","id":42} будет воспринят как данные, а не отображён как веб-страница.
Правило «headers already sent»
Это самое важное, что нужно знать о header(): функция должна вызываться до того, как скрипт отправит какой-либо вывод. Вывод включает HTML, echo/print, var_dump() и даже случайный пробел или пустую строку перед открывающим тегом <?php. Как только отправлен хотя бы один байт тела, раздел заголовков закрывается и PHP выдаёт:
Warning: Cannot modify header information - headers already sentЕсть два способа избежать этой ошибки:
<?php
// 1. Check first — useful when a header is optional
if (!headers_sent()) {
header("X-Powered-By: MyApp");
}
// 2. Buffer output so nothing is flushed until you choose to
ob_start(); // capture everything that gets echoed
echo "page content...";
header("X-Cache: MISS"); // still works — body is held in the buffer
ob_end_flush(); // now send headers + buffered body togetherЧастая причина ошибки — редактор, сохраняющий файл с UTF-8 BOM или переносом строки после ?>. Самый надёжный способ избежать этого — полностью опустить закрывающий тег ?> в файлах с чистым PHP-кодом.
Распространённые сценарии использования
Перенаправление на другой URL
Отправьте заголовок Location, затем остановите скрипт, чтобы дальнейший код не выполнялся:
<?php
header("Location: https://example.com/login");
exit; // always exit after a redirectПо умолчанию это редирект 302 Found (временный). Для постоянного перемещения передайте 301 в качестве кода статуса, чтобы поисковые системы обновили свой индекс:
<?php
// 301 Moved Permanently
header("Location: https://example.com/new-page", true, 301);
exit;Отправка произвольного кода статуса
Вы можете задать статус без перенаправления — например, для API, возвращающего «не найдено»:
<?php
header("HTTP/1.1 404 Not Found");
// or, more portably:
header("Status: 404 Not Found", true, 404);
echo "Resource not found";Для управления кодами статуса специально предназначена функция http_response_code() — она читабельнее и удобнее.
Принудительное скачивание файла
Объедините Content-Type с Content-Disposition: attachment, чтобы браузер сохранял файл вместо его отображения:
<?php
$file = "report.pdf";
header("Content-Type: application/pdf");
header("Content-Disposition: attachment; filename=\"$file\"");
header("Content-Length: " . filesize($file));
readfile($file); // stream the file to the client
exit;См. readfile() для потоковой передачи содержимого файла в вывод.
Управление кешированием браузера
Заголовки позволяют указать браузеру, может ли он повторно использовать ответ и как долго:
<?php
// Tell the browser never to cache this response
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Expires: 0");Отправка нескольких заголовков с одинаковым именем
Большинство заголовков заменяют предыдущий заголовок с тем же именем. Установите второй аргумент в false, если вам действительно нужно несколько заголовков с одним именем (редко, но допустимо для некоторых заголовков):
<?php
header("X-Sample: first");
header("X-Sample: second", false); // both X-Sample headers are sentСвязанные функции
header() записывает по одному заголовку за раз, но в PHP есть высокоуровневые вспомогательные функции для наиболее распространённых случаев:
setcookie()иsetrawcookie()— устанавливают заголовокSet-Cookieбез необходимости форматировать его вручную. См. PHP Cookies.http_response_code()— читает или задаёт код статуса.- PHP Sessions —
session_start()сама отправляет заголовки cookie, поэтому на неё распространяется то же требование «до вывода».
Чтобы подробнее изучить создание и вызов собственных функций, см. PHP Functions.
Заключение
Функция header() — это прямой доступ к HTTP-заголовкам ответа в PHP. Правила просты: сформируйте строку заголовка, вызовите header() до любого вывода и выполните exit после редиректа. С её помощью вы можете перенаправлять пользователей, задавать типы содержимого, отдавать файлы для скачивания, отправлять коды статуса и управлять кешированием — это строительные блоки практически любого динамического PHP-ответа.