You may use the following function to send a status change:
function header_status($statusCode) {
static $status_codes = null;
if ($status_codes === null) {
$status_codes = array (
100 => 'Continue',
101 => 'Switching Protocols',
102 => 'Processing',
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
203 => 'Non-Authoritative Information',
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
207 => 'Multi-Status',
300 => 'Multiple Choices',
301 => 'Moved Permanently',
302 => 'Found',
303 => 'See Other',
304 => 'Not Modified',
305 => 'Use Proxy',
307 => 'Temporary Redirect',
400 => 'Bad Request',
401 => 'Unauthorized',
402 => 'Payment Required',
403 => 'Forbidden',
404 => 'Not Found',
405 => 'Method Not Allowed',
406 => 'Not Acceptable',
407 => 'Proxy Authentication Required',
408 => 'Request Timeout',
409 => 'Conflict',
410 => 'Gone',
411 => 'Length Required',
412 => 'Precondition Failed',
413 => 'Request Entity Too Large',
414 => 'Request-URI Too Long',
415 => 'Unsupported Media Type',
416 => 'Requested Range Not Satisfiable',
417 => 'Expectation Failed',
422 => 'Unprocessable Entity',
423 => 'Locked',
424 => 'Failed Dependency',
426 => 'Upgrade Required',
500 => 'Internal Server Error',
501 => 'Not Implemented',
502 => 'Bad Gateway',
503 => 'Service Unavailable',
504 => 'Gateway Timeout',
505 => 'HTTP Version Not Supported',
506 => 'Variant Also Negotiates',
507 => 'Insufficient Storage',
509 => 'Bandwidth Limit Exceeded',
510 => 'Not Extended'
);
}
if ($status_codes[$statusCode] !== null) {
$status_string = $statusCode . ' ' . $status_codes[$statusCode];
header($_SERVER['SERVER_PROTOCOL'] . ' ' . $status_string, true, $statusCode);
}
}
You may use it as such:
<?php
header_status(500);
if (that_happened) {
die("that happened")
}
if (something_else_happened) {
die("something else happened")
}
update_database();
header_status(200);
- Предыдующая статья: Делаем собственную страницу ошибки 404
2019-12-01
Здравствуйте, уважаемый посетитель!
Сегодня в рамах рассмотрения системы обработки ошибок выполним необходимые действия по выводу пользователю сообщения о возникновении внутренней ошибки сервера Internal Server Error, соответствующей статусу HTTP 500.
Это необходимо сделать, так как никто не застрахован от возникновения подобных проблем. В таких случаях, если не предпринять соответстующих мер, пользователь в своем браузере будет видеть только лишь какой-нибудь ущербный, неполноценный вариант веб-страницы. Либо вообще пустой экран или страницу в несколько строк с непонятными для него техническими терминами.
И вот для того, чтобы упорядочить работу сайта, обеспечивая пользователя при любых ситуациях необходимой информацией, мы создадим собственную страницу 500.
А затем, для обеспечения на нее перенаправления, сформируем пользовательский обработчик фатальных ошибок PHP. Который в дальнейшем поможет нам обеспечить и другие возможности создаваемого механизма, такие как сохранение логов и отправка сообщений по email.
- Создание страницы 500
- Перехват и обработка фатальных ошибок PHP
- Буферизация вывода в PHP
- Дополнение файла .htaccess
- Проверка работы сайта при внутренней ошибке сервера
- Исходные файлы сайта
Создание страницы 500
В первую очередь создадим в корне сайта новый файл с соответствующим именем, например «page_500.php». И поместим в него код страницы, которая будет отображаться при возникновении ошибки 500. А выполним это аналогично тому, как мы это делали в предыдущей статье при создании страницы 404.
Правда, сделаем это с некоторым отличием, заключающимся в том, что в этот раз при ее формировании будем использовать только разметку HTML, исключая какое-либо использование PHP.
Ведь не логично применять фрагменты кода, которые в случае возникновения фатальной ошибки PHP могут повлиять на отправку страницы, предназначенную, как раз, для обработки таких нестандартных ситуаций.
Конечно, это не относится к применению функции header(), с помощью которой отправляется HTTP заголовок с кодом 500, соответствующий внутренней ошибки сервера (строка 2 в приведенном ниже коде).
kak-vyvesti-stranicu-oshibki-500_1
Рис.1 Файл «page_500.php» с HTML-кодом страницы 500
Как видно, данный вариант по структуре полностью соответствует предыдущей странице 404, но выполнен на чистом HTML. Причем все общие блоки: шапка, меню, основное содержание и футер включены непосредственно, без применения подключающих инструкций PHP.
Что касается оформления, то в данном случае этого не требуется, так HTML-код страницы мало чем отличается от предыдущей. И как следствие, все необходимые свойства уже ранее назначены и добавлены в таблицу стилей CSS.
И в этом можно убедиться, если сейчас открыть созданную страницу через адресную строку браузера, добавив к доменному имени ее адрес /page_500.php. Как и в предыдущем случае в начале сделаем это в обычном, десктопном варианте пользовательского устройства.

Рис.2 Вид созданной страницы 500
А теперь посмотрим как это будет выглядеть при малом разрешении экрана в одно колоночном исполнении.

Рис.3 Вид страницы 500 при малом разрешении экрана
Как видно, полученная страница по форме схожа с предыдущей 404. За исключением содержания, отражающего теперь информацию о возникновении внутренней ошибки сервера, соответствующей статусу 500 протокола HTTP.
Таким образом необходимая страница создана. И теперь осталось только обеспечить на нее перенаправление.
Перехват и обработка фатальных ошибок PHP
Как ранее отмечалось, внутренняя ошибка сервера наиболее часто возникает в следствии фатальных ошибок PHP. Причем такие случаи обычно сопровождаются остановкой скрипта. Отчего идентифицировать такую ошибку с помощью того же самого скрипта не получится. Так как в этом случае выполнение в нем каких-либо последующих действий не представляется возможным.
Как вариант решения этой проблемы — применение встроенной функции обратного вызова register_shutdown_function(), предназначенной для регистрации специальной пользовательской функции, не связанной с работой скрипта. И, следовательно, способной выполнить дальнейшие преобразования, несмотря на то, что сам скрипт остановлен.
И таким образом, в случае возникновения фатальной ошибки управление передается этой зарегистрированной функции, являющейся в данном случае обработчиком.
Как может выглядеть регистрация пользовательской функции и перехват в ней последней ошибки, остановившей работу скрипта, показано в следующем фрагменте PHP-кода.
-
//—-Перехват и обработка фатальных ошибок PHP—-
-
function fatal_php(){ //Пользовательская функция
-
$error = error_get_last(); //Получение информации о последней произошедшей ошибке
-
if ($error !== NULL && in_array($error[‘type’], array(E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR))){ //Если ошибка произошла и ее тип соответствует фатальной ошибке
-
$domen = ‘http://’.$_SERVER[‘SERVER_NAME’]; //Домен сайта
-
header(«Location: $domen/page_500.php»); //Редирект на страницу 500
-
exit; //Прекращение выполнения текущего скрипта
-
}
-
}
-
register_shutdown_function(‘fatal_php’); //Регистрация пользовательской функции обработчика фатальных ошибок PHP
-
?>
Рис.4 Перехват и обработка фатальных ошибок PHP
Здесь все строки кода сопровождаются комментариями, поэтому подробно описывать каждую из них, нет смысла.
Можно лишь отметить, что регистрация пользовательской функции выполняется, как ранее было отмечено, с помощью register_shutdown_function(), расположенной в строке 11.
А сама функция обработчика с именем fatal_php() (поз.3÷10) в начале возвращает ассоциативный массив с описанием последней произошедшей ошибки (функция error_get_last() поз.4). А затем в случае, если выявленная ошибка относится к одному из четырех необходимых типов (E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR), то с помощью функции отправки HTTP-заголовка header() (поз.7) выполняется редирект по указанному аргументом «Location» адресу, соответствующему странице 500.
В случае, если фатальная ошибка PHP возникает в процессе формирования тела страницы при отправленном HTTP-заголовке, то при установках по умолчанию, в соответствии с протоколом HTTP должна возникнуть ошибка Cannot modify header information — headers already sent by (), означающая невозможность изменения заголовка после его отправки. Более подробно об этом и о том, как решить эту проблему мы посмотрим в следующем разделе статьи.
Таким образом при использовании созданной пользовательской функции, в случае, если из-за какой-то критической ошибки PHP-скрипт остановлен, обработчик ее обнаружит и выполнит необходимые действия по ее идентификации и дальнейшей обработке.
В данном случае обработка заключается всего лишь в выполнении редиректа на страницу 500. Но в дальнейшем, когда мы перейдем к сохранению логов и оправке сообщений по email, то здесь же будем использовать и другие, необходимые для этого преобразования.
И последнее, на что необходимо обратить внимание, функция обработчика должна быть расположена в самом начале кода шаблона главной страницы файла index.php. Иными словами, чтобы все остальные PHP-инструкции, используемые при формировании веб-страницы, выполнялись только после ее регистрации. В противном случае при остановке скрипта обработчик не будет вызван и, соответственно, не сможет выполнить свою задачу.
Буферизация вывода в PHP
В созданном обработчике фатальных ошибок PHP (рис.2) с помощью функции HTTP-заголовка header() (поз.7) предусматривается редирект на страницу 500.
Однако, здесь следует учесть одно обстоятельство, а именно: в случае редиректа, выполняемого в момент формирования тела веб-страницы, уже после отправки HTTP-заголовка, непременно должна последовать ошибка Cannot modify header information — headers already sent by ().
Обусловлено это следующим. По умолчанию сервер отправляет в браузер данные веб-страницы по мере их готовности, в процессе выполнения PHP-скрипта. При этом в соответствии с протоколом HTTP, сервер в ответ на запрос должен в первую очередь отправить служебные заголовки, а уж только потом код самого тела страницы. И протоколом HTTP не допускается ситуация, когда в момент передачи тела страницы производится повторная оправка HTTP-заголовка. О чем и говорит описание вышеуказанной ошибки.
В подтверждение этому можно проверить работу созданного обработчика по состоянию на данный момент, с заведомо внесенной критической ошибкой PHP.
На скриншоте показан вариант вывода страницы «Получить скидку», у которой в код PHP файла poluchit-skidku.php специально внесена синтаксическая ошибка.

Рис.5 Ошибка при изменении заголовка после его отправки
Как видно, здесь в области основного содержания, при обнаружении в ней фатальной ошибки Parse error и остановки скрипта, присутствует также и ошибка Cannot modify header information — headers already sent by (), означающая невозможность изменения заголовка в момент передачи кода данного блока веб-страницы.
А для того, чтобы решить эту проблему и иметь возможность изменять в любой момент HTTP-заголовки, применяется, так называемая буферизация вывода в PHP.
Суть ее в том, что в этом случае при выполнении PHP, сервер не оправляет страницу по мере ее готовности, а складывает полученный код в определенный буфер, параллельно формируя HTTP-заголовки, которые в обычном режиме не допускается оправлять в момент передачи тела страницы.
И только после того, как скрипт выполнит все заложенные в него операции, то всё, что в конечном итоге оказалось в буфере, разом отправляется в браузер пользователя в правильном порядке, как это определенно протоколом HTTP — сначала заголовки, а уж потом страница, сформированная скриптом.
В PHP существуют несколько функций, предназначенных для работы с буфером. Но для данной задачи мы будем использовать только две из них ob_start() — для включения буферизации вывода и ob_end_flush() — для отправки данных из буфера и отключения буферизации.
Схематично для генерируемой HTML-страницы это можно представить следующим образом.
kak-vyvesti-stranicu-oshibki-500_2
Рис.6 Буферизация вывода в PHP
А ниже показано, как в итоге будет выглядеть код шаблона главной страницы в файле index.php после дополнения его обработчиком фатальных ошибок PHP и элементами буферизации вывода PHP (светлым фоном обозначены дополнительные фрагмента кода).
kak-vyvesti-stranicu-oshibki-500_3
Рис.7 Файл index.php с обработчиком ошибок и буферизацией вывода
Следует отметить, что для оптимизации файла index.php, ранее размещенный в начале шаблона главной страницы PHP-код, предназначенный для получения данных при формировании динамической страницы, перенесен в файл start.php, который подключается соответствующей инструкцией в строке 13.
Таким образом буферизацию вывода HTML-страницы, генерированной скриптом PHP, мы выполнили. Однако, для полноценной работы сайта при обработке ошибки 500 необходимо сделать еще одно небольшое дополнение, которые мы сейчас и рассмотрим.
Дополнение файла .htaccess
Приведенные выше преобразования предназначены для выполнения редиректа на страницу 500 в случае прерывания работы скрипта при фатальных ошибках PHP.
Но для того, чтобы это происходило и в других случаях внутренней ошибки сервера, необходимо в файл .htaccess добавить директиву ErrorDocument, аналогичную той, которую мы использовали ранее при редиректе на страницу 404. Только теперь в ней должен быть указан соответствующий адрес /page_500.php.
А заодно, в целях безопасности полезно будет вообще отключить отображение системных сообщений на экране пользователя. Так как теперь возникающие по каким-либо причинам ошибки будут фиксироваться собственным механизмом обработки ошибок и нет необходимости их выводить в браузер. Тем более, что в определенных случаях такая излишняя для пользователя информация может быть использована недоброжелателями в качестве уязвимости сайта.
В итоге файл .htaccess следует дополнить следующими директивами, которые обеспечат выполнение вышеперечисленных действий.
-
ErrorDocument 500 /page_500.php
-
php_flag display_errors 0
Рис.8 Редирект 500 в файле .htaccess
Таким образом мы сделали все необходимые преобразования для вывода страницы 500. И теперь можно проверить, как это в реальности будет работать.
Проверка работы сайта при внутренней ошибке сервера
Проверку обработки внутренней ошибки сервера выполним на примере возникновения фатальной ошибки PHP, что позволит удостовериться в корректной работе, как созданного обработчики фатальных ошибок, так и процесса буферизации вывода генерируемой страницы и редиректа на страницу 500.
Для этого в код PHP временно внесем ту же самую синтаксическую ошибку, которую ранее мы делали на промежуточном этапе (рис.5). И посмотрим, как теперь будет обработана такая ситуация.

Рис.9 Вывод страницы 500 при фатальной ошибке PHP
Как видно, теперь критическая ошибка отработана должным образом, с перенаправлением на страницу ошибки 500.
При желании, можно проверить работу сайта и при других искусственно созданных фатальных ошибках. И во всех случаях результат должен быть один — отображение собственной страницы 500. Что в итоге и требовалось получить.
В следующей статье мы создадим механизм обработки не фатальных ошибок PHP, где с помощью собственного обработчика будет обеспечиваться их перехват и сохранение сообщений в соответствующем журнале.
.
Исходные файлы сайта
Исходные файлы сайта с обновлениями, которые были сделаны в данной статье, можно скачать из прилагаемых дополнительных материалов:
- Файлы каталога www
- Таблицы базы данных MySQL
Дополнительные материалы бесплатно предоставляются только зарегистрированным пользователям.
Для скачивания исходных файлов необходимо авторизоваться под своим аккаунтом через соответствующую форму.
Для тех кто не зарегистрирован, можно это сделать на вкладке Регистрация.
С уважением,
- Следующая сатья: Перехват и обработка не фатальных ошибок PHP
Если у Вас возникли вопросы, или есть какие-либо пожелания по представлению материала, либо заметили какие-нибудь ошибки, а быть может просто хотите выразить свое мнение, пожалуйста, оставьте свои комментарии. Такая обратная связь очень важна для возможности учета мнения посетителей.
Буду Вам за это очень признателен!
This has never happened before. Usually it displays the error, but now it just gives me a 500 internal server error. Of course before, when it displayed the error, it was different servers. Now I’m on a new server (I have full root, so if I need to configure it somewhere in the php.ini, I can.) Or perhaps its something with Apache?
I’ve been putting up with it by just transferring the file to my other server and running it there to find the error, but that’s become too tedious. Is there a way to fix this?
asked Apr 22, 2010 at 1:45
1
Check the error_reporting, display_errors and display_startup_errors settings in your php.ini file. They should be set to E_ALL and "On" respectively (though you should not use display_errors on a production server, so disable this and use log_errors instead if/when you deploy it). You can also change these settings (except display_startup_errors) at the very beginning of your script to set them at runtime (though you may not catch all errors this way):
error_reporting(E_ALL);
ini_set('display_errors', 'On');
After that, restart server.
![]()
Davide
1,5951 gold badge14 silver badges29 bronze badges
answered Apr 22, 2010 at 1:49
awgyawgy
16.4k4 gold badges25 silver badges18 bronze badges
7
Use php -l <filename> (that’s an ‘L’) from the command line to output the syntax error that could be causing PHP to throw the status 500 error. It’ll output something like:
PHP Parse error: syntax error, unexpected '}' in <filename> on line 18
![]()
Matthew Lock
12.6k11 gold badges89 silver badges128 bronze badges
answered May 25, 2016 at 3:53
AaronAaron
5835 silver badges12 bronze badges
3
It’s worth noting that if your error is due to .htaccess, for example a missing rewrite_module, you’ll still see the 500 internal server error.
answered Aug 4, 2014 at 1:53
dtbarnedtbarne
8,0505 gold badges43 silver badges48 bronze badges
1
Be careful to check if
display_errors
or
error_reporting
is active (not a comment) somewhere else in the ini file.
My development server refused to display errors after upgrade to
Kubuntu 16.04 — I had checked php.ini numerous times … turned out that there was a diplay_errors = off; about 100 lines below my
display_errors = on;
So remember the last one counts!
answered Sep 9, 2016 at 15:17
![]()
MaxMax
2,4811 gold badge22 silver badges27 bronze badges
Try not to go
MAMP > conf > [your PHP version] > php.ini
but
MAMP > bin > php > [your PHP version] > conf > php.ini
and change it there, it worked for me…
answered Mar 20, 2017 at 20:57
![]()
Enabling error displaying from PHP code doesn’t work out for me. In my case, using NGINX and PHP-FMP, I track the log file using grep. For instance, I know the file name mycode.php causes the error 500, but don’t know which line. From the console, I use this:
/var/log/php-fpm# cat www-error.log | grep mycode.php
And I have the output:
[04-Apr-2016 06:58:27] PHP Parse error: syntax error, unexpected ';' in /var/www/html/system/mycode.php on line 1458
This helps me find the line where I have the typo.
answered Apr 4, 2016 at 5:05
Hao NguyenHao Nguyen
5184 silver badges9 bronze badges
If all else fails try moving (i.e. in bash) all files and directories «away» and adding them back one by one.
I just found out that way that my .htaccess file was referencing a non-existant .htpasswd file. (#silly)
answered Mar 6, 2017 at 12:16
![]()
This has never happened before. Usually it displays the error, but now it just gives me a 500 internal server error. Of course before, when it displayed the error, it was different servers. Now I’m on a new server (I have full root, so if I need to configure it somewhere in the php.ini, I can.) Or perhaps its something with Apache?
I’ve been putting up with it by just transferring the file to my other server and running it there to find the error, but that’s become too tedious. Is there a way to fix this?
asked Apr 22, 2010 at 1:45
1
Check the error_reporting, display_errors and display_startup_errors settings in your php.ini file. They should be set to E_ALL and "On" respectively (though you should not use display_errors on a production server, so disable this and use log_errors instead if/when you deploy it). You can also change these settings (except display_startup_errors) at the very beginning of your script to set them at runtime (though you may not catch all errors this way):
error_reporting(E_ALL);
ini_set('display_errors', 'On');
After that, restart server.
![]()
Davide
1,5951 gold badge14 silver badges29 bronze badges
answered Apr 22, 2010 at 1:49
awgyawgy
16.4k4 gold badges25 silver badges18 bronze badges
7
Use php -l <filename> (that’s an ‘L’) from the command line to output the syntax error that could be causing PHP to throw the status 500 error. It’ll output something like:
PHP Parse error: syntax error, unexpected '}' in <filename> on line 18
![]()
Matthew Lock
12.6k11 gold badges89 silver badges128 bronze badges
answered May 25, 2016 at 3:53
AaronAaron
5835 silver badges12 bronze badges
3
It’s worth noting that if your error is due to .htaccess, for example a missing rewrite_module, you’ll still see the 500 internal server error.
answered Aug 4, 2014 at 1:53
dtbarnedtbarne
8,0505 gold badges43 silver badges48 bronze badges
1
Be careful to check if
display_errors
or
error_reporting
is active (not a comment) somewhere else in the ini file.
My development server refused to display errors after upgrade to
Kubuntu 16.04 — I had checked php.ini numerous times … turned out that there was a diplay_errors = off; about 100 lines below my
display_errors = on;
So remember the last one counts!
answered Sep 9, 2016 at 15:17
![]()
MaxMax
2,4811 gold badge22 silver badges27 bronze badges
Try not to go
MAMP > conf > [your PHP version] > php.ini
but
MAMP > bin > php > [your PHP version] > conf > php.ini
and change it there, it worked for me…
answered Mar 20, 2017 at 20:57
![]()
Enabling error displaying from PHP code doesn’t work out for me. In my case, using NGINX and PHP-FMP, I track the log file using grep. For instance, I know the file name mycode.php causes the error 500, but don’t know which line. From the console, I use this:
/var/log/php-fpm# cat www-error.log | grep mycode.php
And I have the output:
[04-Apr-2016 06:58:27] PHP Parse error: syntax error, unexpected ';' in /var/www/html/system/mycode.php on line 1458
This helps me find the line where I have the typo.
answered Apr 4, 2016 at 5:05
Hao NguyenHao Nguyen
5184 silver badges9 bronze badges
If all else fails try moving (i.e. in bash) all files and directories «away» and adding them back one by one.
I just found out that way that my .htaccess file was referencing a non-existant .htpasswd file. (#silly)
answered Mar 6, 2017 at 12:16
![]()
(PHP 5 >= 5.4.0, PHP 7, PHP 8)
http_response_code — Получает или устанавливает код ответа HTTP
Описание
http_response_code(int $response_code = 0): int|bool
Список параметров
-
response_code -
Код ответа устанавливается с помощью опционального параметра
response_code.
Возвращаемые значения
Если response_code задан, то будет возвращён предыдущий код
статуса. Если response_code не задан, то будет возвращён
текущий код статуса. Оба этих значения будут по умолчанию иметь код состояния 200,
если они используются в окружении веб-сервера.
Если response_code не задан и используется не в окружении
веб-сервера (например, в CLI), то будет возвращено false. Если
response_code задан и используется не в окружении
веб-сервера, то будет возвращено true (но только если не был установлен предыдущий
код статуса).
Примеры
Пример #1 Использование http_response_code() в окружении веб-сервера
<?php// Берём текущий код и устанавливаем новый
var_dump(http_response_code(404));// Берём новый код
var_dump(http_response_code());
?>
Результат выполнения данного примера:
Пример #2 Использование http_response_code() в CLI
<?php// Берём текущий код по умолчанию
var_dump(http_response_code());// Устанавливаем код
var_dump(http_response_code(201));// Берём новый код
var_dump(http_response_code());
?>
Результат выполнения данного примера:
bool(false) bool(true) int(201)
Смотрите также
- header() — Отправка HTTP-заголовка
- headers_list() — Возвращает список переданных заголовков (или готовых к отправке)
craig at craigfrancis dot co dot uk ¶
11 years ago
If your version of PHP does not include this function:
<?phpif (!function_exists('http_response_code')) {
function http_response_code($code = NULL) {
if (
$code !== NULL) {
switch (
$code) {
case 100: $text = 'Continue'; break;
case 101: $text = 'Switching Protocols'; break;
case 200: $text = 'OK'; break;
case 201: $text = 'Created'; break;
case 202: $text = 'Accepted'; break;
case 203: $text = 'Non-Authoritative Information'; break;
case 204: $text = 'No Content'; break;
case 205: $text = 'Reset Content'; break;
case 206: $text = 'Partial Content'; break;
case 300: $text = 'Multiple Choices'; break;
case 301: $text = 'Moved Permanently'; break;
case 302: $text = 'Moved Temporarily'; break;
case 303: $text = 'See Other'; break;
case 304: $text = 'Not Modified'; break;
case 305: $text = 'Use Proxy'; break;
case 400: $text = 'Bad Request'; break;
case 401: $text = 'Unauthorized'; break;
case 402: $text = 'Payment Required'; break;
case 403: $text = 'Forbidden'; break;
case 404: $text = 'Not Found'; break;
case 405: $text = 'Method Not Allowed'; break;
case 406: $text = 'Not Acceptable'; break;
case 407: $text = 'Proxy Authentication Required'; break;
case 408: $text = 'Request Time-out'; break;
case 409: $text = 'Conflict'; break;
case 410: $text = 'Gone'; break;
case 411: $text = 'Length Required'; break;
case 412: $text = 'Precondition Failed'; break;
case 413: $text = 'Request Entity Too Large'; break;
case 414: $text = 'Request-URI Too Large'; break;
case 415: $text = 'Unsupported Media Type'; break;
case 500: $text = 'Internal Server Error'; break;
case 501: $text = 'Not Implemented'; break;
case 502: $text = 'Bad Gateway'; break;
case 503: $text = 'Service Unavailable'; break;
case 504: $text = 'Gateway Time-out'; break;
case 505: $text = 'HTTP Version not supported'; break;
default:
exit('Unknown http status code "' . htmlentities($code) . '"');
break;
}$protocol = (isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0');header($protocol . ' ' . $code . ' ' . $text);$GLOBALS['http_response_code'] = $code;
} else {
$code = (isset($GLOBALS['http_response_code']) ? $GLOBALS['http_response_code'] : 200);
}
return
$code;
}
}
?>
In this example I am using $GLOBALS, but you can use whatever storage mechanism you like... I don't think there is a way to return the current status code:
https://bugs.php.net/bug.php?id=52555
For reference the error codes I got from PHP's source code:
http://lxr.php.net/opengrok/xref/PHP_5_4/sapi/cgi/cgi_main.c#354
And how the current http header is sent, with the variables it uses:
http://lxr.php.net/opengrok/xref/PHP_5_4/main/SAPI.c#856
Stefan W ¶
8 years ago
Note that you can NOT set arbitrary response codes with this function, only those that are known to PHP (or the SAPI PHP is running on).
The following codes currently work as expected (with PHP running as Apache module):
200 – 208, 226
300 – 305, 307, 308
400 – 417, 422 – 424, 426, 428 – 429, 431
500 – 508, 510 – 511
Codes 0, 100, 101, and 102 will be sent as "200 OK".
Everything else will result in "500 Internal Server Error".
If you want to send responses with a freestyle status line, you need to use the `header()` function:
<?php header("HTTP/1.0 418 I'm A Teapot"); ?>
Thomas A. P. ¶
7 years ago
When setting the response code to non-standard ones like 420, Apache outputs 500 Internal Server Error.
This happens when using header(0,0,420) and http_response_code(420).
Use header('HTTP/1.1 420 Enhance Your Calm') instead.
Note that the response code in the string IS interpreted and used in the access log and output via http_response_code().
Anonymous ¶
9 years ago
Status codes as an array:
<?php
$http_status_codes = array(100 => "Continue", 101 => "Switching Protocols", 102 => "Processing", 200 => "OK", 201 => "Created", 202 => "Accepted", 203 => "Non-Authoritative Information", 204 => "No Content", 205 => "Reset Content", 206 => "Partial Content", 207 => "Multi-Status", 300 => "Multiple Choices", 301 => "Moved Permanently", 302 => "Found", 303 => "See Other", 304 => "Not Modified", 305 => "Use Proxy", 306 => "(Unused)", 307 => "Temporary Redirect", 308 => "Permanent Redirect", 400 => "Bad Request", 401 => "Unauthorized", 402 => "Payment Required", 403 => "Forbidden", 404 => "Not Found", 405 => "Method Not Allowed", 406 => "Not Acceptable", 407 => "Proxy Authentication Required", 408 => "Request Timeout", 409 => "Conflict", 410 => "Gone", 411 => "Length Required", 412 => "Precondition Failed", 413 => "Request Entity Too Large", 414 => "Request-URI Too Long", 415 => "Unsupported Media Type", 416 => "Requested Range Not Satisfiable", 417 => "Expectation Failed", 418 => "I'm a teapot", 419 => "Authentication Timeout", 420 => "Enhance Your Calm", 422 => "Unprocessable Entity", 423 => "Locked", 424 => "Failed Dependency", 424 => "Method Failure", 425 => "Unordered Collection", 426 => "Upgrade Required", 428 => "Precondition Required", 429 => "Too Many Requests", 431 => "Request Header Fields Too Large", 444 => "No Response", 449 => "Retry With", 450 => "Blocked by Windows Parental Controls", 451 => "Unavailable For Legal Reasons", 494 => "Request Header Too Large", 495 => "Cert Error", 496 => "No Cert", 497 => "HTTP to HTTPS", 499 => "Client Closed Request", 500 => "Internal Server Error", 501 => "Not Implemented", 502 => "Bad Gateway", 503 => "Service Unavailable", 504 => "Gateway Timeout", 505 => "HTTP Version Not Supported", 506 => "Variant Also Negotiates", 507 => "Insufficient Storage", 508 => "Loop Detected", 509 => "Bandwidth Limit Exceeded", 510 => "Not Extended", 511 => "Network Authentication Required", 598 => "Network read timeout error", 599 => "Network connect timeout error");
?>
Source: Wikipedia "List_of_HTTP_status_codes"
viaujoc at videotron dot ca ¶
2 years ago
Do not mix the use of http_response_code() and manually setting the response code header because the actual HTTP status code being returned by the web server may not end up as expected. http_response_code() does not work if the response code has previously been set using the header() function. Example:
<?php
header('HTTP/1.1 401 Unauthorized');
http_response_code(403);
print(http_response_code());
?>
The raw HTTP response will be (notice the actual status code on the first line does not match the printed http_response_code in the body):
HTTP/1.1 401 Unauthorized
Date: Tue, 24 Nov 2020 13:49:08 GMT
Server: Apache
Connection: Upgrade, Keep-Alive
Keep-Alive: timeout=5, max=100
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8
403
I only tested it on Apache. I am not sure if this behavior is specific to Apache or common to all PHP distributions.
Anonymous ¶
8 years ago
You can also create a enum by extending the SplEnum class.
<?php/** HTTP status codes */
class HttpStatusCode extends SplEnum {
const __default = self::OK;
const
SWITCHING_PROTOCOLS = 101;
const OK = 200;
const CREATED = 201;
const ACCEPTED = 202;
const NONAUTHORITATIVE_INFORMATION = 203;
const NO_CONTENT = 204;
const RESET_CONTENT = 205;
const PARTIAL_CONTENT = 206;
const MULTIPLE_CHOICES = 300;
const MOVED_PERMANENTLY = 301;
const MOVED_TEMPORARILY = 302;
const SEE_OTHER = 303;
const NOT_MODIFIED = 304;
const USE_PROXY = 305;
const BAD_REQUEST = 400;
const UNAUTHORIZED = 401;
const PAYMENT_REQUIRED = 402;
const FORBIDDEN = 403;
const NOT_FOUND = 404;
const METHOD_NOT_ALLOWED = 405;
const NOT_ACCEPTABLE = 406;
const PROXY_AUTHENTICATION_REQUIRED = 407;
const REQUEST_TIMEOUT = 408;
const CONFLICT = 408;
const GONE = 410;
const LENGTH_REQUIRED = 411;
const PRECONDITION_FAILED = 412;
const REQUEST_ENTITY_TOO_LARGE = 413;
const REQUESTURI_TOO_LARGE = 414;
const UNSUPPORTED_MEDIA_TYPE = 415;
const REQUESTED_RANGE_NOT_SATISFIABLE = 416;
const EXPECTATION_FAILED = 417;
const IM_A_TEAPOT = 418;
const INTERNAL_SERVER_ERROR = 500;
const NOT_IMPLEMENTED = 501;
const BAD_GATEWAY = 502;
const SERVICE_UNAVAILABLE = 503;
const GATEWAY_TIMEOUT = 504;
const HTTP_VERSION_NOT_SUPPORTED = 505;
}
divinity76 at gmail dot com ¶
2 years ago
if you need a response code not supported by http_response_code(), such as WebDAV / RFC4918's "HTTP 507 Insufficient Storage", try:
<?php
header($_SERVER['SERVER_PROTOCOL'] . ' 507 Insufficient Storage');
?>
result: something like
HTTP/1.1 507 Insufficient Storage
Rob Zazueta ¶
9 years ago
The note above from "Anonymous" is wrong. I'm running this behind the AWS Elastic Loadbalancer and trying the header(':'.$error_code...) method mentioned above is treated as invalid HTTP.
The documentation for the header() function has the right way to implement this if you're still on < php 5.4:
<?php
header("HTTP/1.0 404 Not Found");
?>
Anonymous ¶
10 years ago
If you don't have PHP 5.4 and want to change the returned status code, you can simply write:
<?php
header(':', true, $statusCode);
?>
The ':' are mandatory, or it won't work
Steven ¶
7 years ago
http_response_code is basically a shorthand way of writing a http status header, with the added bonus that PHP will work out a suitable Reason Phrase to provide by matching your response code to one of the values in an enumeration it maintains within php-src/main/http_status_codes.h. Note that this means your response code must match a response code that PHP knows about. You can't create your own response codes using this method, however you can using the header method.
In summary - The differences between "http_response_code" and "header" for setting response codes:
1. Using http_response_code will cause PHP to match and apply a Reason Phrase from a list of Reason Phrases that are hard-coded into the PHP source code.
2. Because of point 1 above, if you use http_response_code you must set a code that PHP knows about. You can't set your own custom code, however you can set a custom code (and Reason Phrase) if you use the header method.
Richard F. ¶
9 years ago
At least on my side with php-fpm and nginx this method does not change the text in the response, only the code.
<?php// HTTP/1.1 404 Not Found
http_response_code(404);?>
The resulting response is HTTP/1.1 404 OK
stephen at bobs-bits dot com ¶
8 years ago
It's not mentioned explicitly, but the return value when SETTING, is the OLD status code.
e.g.
<?php
$a
= http_response_code();
$b = http_response_code(202);
$c = http_response_code();var_dump($a, $b, $c);// Result:
// int(200)
// int(200)
// int(202)
?>
Chandra Nakka ¶
5 years ago
On PHP 5.3 version, If you want to set HTTP response code. You can try this type of below trick :)
<?php
header
('Temporary-Header: True', true, 404);
header_remove('Temporary-Header');?>
yefremov {dot} sasha () gmail {dot} com ¶
8 years ago
@craig at craigfrancis dot co dot uk@ wrote the function that replaces the original. It is very usefull, but has a bug. The original http_response_code always returns the previous or current code, not the code you are setting now. Here is my fixed version. I also use $GLOBALS to store the current code, but trigger_error() instead of exit. So now, how the function will behave in the case of error lies on the error handler. Or you can change it back to exit().
if (!function_exists('http_response_code')) {
function http_response_code($code = NULL) {
$prev_code = (isset($GLOBALS['http_response_code']) ? $GLOBALS['http_response_code'] : 200);
if ($code === NULL) {
return $prev_code;
}
switch ($code) {
case 100: $text = 'Continue'; break;
case 101: $text = 'Switching Protocols'; break;
case 200: $text = 'OK'; break;
case 201: $text = 'Created'; break;
case 202: $text = 'Accepted'; break;
case 203: $text = 'Non-Authoritative Information'; break;
case 204: $text = 'No Content'; break;
case 205: $text = 'Reset Content'; break;
case 206: $text = 'Partial Content'; break;
case 300: $text = 'Multiple Choices'; break;
case 301: $text = 'Moved Permanently'; break;
case 302: $text = 'Moved Temporarily'; break;
case 303: $text = 'See Other'; break;
case 304: $text = 'Not Modified'; break;
case 305: $text = 'Use Proxy'; break;
case 400: $text = 'Bad Request'; break;
case 401: $text = 'Unauthorized'; break;
case 402: $text = 'Payment Required'; break;
case 403: $text = 'Forbidden'; break;
case 404: $text = 'Not Found'; break;
case 405: $text = 'Method Not Allowed'; break;
case 406: $text = 'Not Acceptable'; break;
case 407: $text = 'Proxy Authentication Required'; break;
case 408: $text = 'Request Time-out'; break;
case 409: $text = 'Conflict'; break;
case 410: $text = 'Gone'; break;
case 411: $text = 'Length Required'; break;
case 412: $text = 'Precondition Failed'; break;
case 413: $text = 'Request Entity Too Large'; break;
case 414: $text = 'Request-URI Too Large'; break;
case 415: $text = 'Unsupported Media Type'; break;
case 500: $text = 'Internal Server Error'; break;
case 501: $text = 'Not Implemented'; break;
case 502: $text = 'Bad Gateway'; break;
case 503: $text = 'Service Unavailable'; break;
case 504: $text = 'Gateway Time-out'; break;
case 505: $text = 'HTTP Version not supported'; break;
default:
trigger_error('Unknown http status code ' . $code, E_USER_ERROR); // exit('Unknown http status code "' . htmlentities($code) . '"');
return $prev_code;
}
$protocol = (isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0');
header($protocol . ' ' . $code . ' ' . $text);
$GLOBALS['http_response_code'] = $code;
// original function always returns the previous or current code
return $prev_code;
}
}
Anonymous ¶
4 years ago
http_response_code() does not actually send HTTP headers, it only prepares the header list to be sent later on.
So you can call http_reponse_code() to set, get and reset the HTTP response code before it gets sent.
Test code:
<php
http_response_code(500); // set the code
var_dump(headers_sent()); // check if headers are sent
http_response_code(200); // avoid a default browser page
Kubo2 ¶
6 years ago
If you want to set a HTTP response code without the need of specifying a protocol version, you can actually do it without http_response_code():
<?php
header
('Status: 404', TRUE, 404);?>
zweibieren at yahoo dot com ¶
7 years ago
The limited list given by Stefan W is out of date. I have just tested 301 and 302 and both work.
divinity76 at gmail dot com ¶
6 years ago
warning, it does not check if headers are already sent (if it is, it won't *actually* change the code, but a subsequent call will imply that it did!!),
you might wanna do something like
function ehttp_response_code(int $response_code = NULL): int {
if ($response_code === NULL) {
return http_response_code();
}
if (headers_sent()) {
throw new Exception('tried to change http response code after sending headers!');
}
return http_response_code($response_code);
}
Я знаю, что это старая ветка, но когда я искал в Google, она выскакивает как первый ответ. В последнее время я пытался понять, как это сделать, поэтому думаю, что мне следует опубликовать обходной путь с 2018 года.
Как вы все знаете, нет, вы не можете просто запускать страницы ошибок Apache из PHP. Нет никакого способа сделать это. Итак, лучший обходной путь, который я смог найти после некоторого исследования, — это использовать функцию PHP для отображения настраиваемых страниц ошибок, который вызывается как из того, что вы указали в Apache, так и из страницы, на которой вы хотите вызвать 500 Internal Server Error.
Вот моя conf Apache:
ErrorDocument 400 /error.php
ErrorDocument 401 /error.php
ErrorDocument 403 /error.php
ErrorDocument 404 /error.php
ErrorDocument 500 /error.php
Как видите, все ошибки 4xx и 500 перенаправляются в один и тот же файл php. Почему я не использую отдельные файлы для каждого кода — это еще один вопрос, который не имеет ничего общего с вашим вопросом здесь, поэтому давайте забудем об этом и сосредоточимся на error.php на данный момент.
Вот несколько строк error.php:
<?php
require_once("error_page.php");
$relative_path = "";
$internal_server_error = FALSE;
if (isset($_SERVER['REDIRECT_URL']) && $_SERVER['REDIRECT_URL'] != "")
{
$relative_path = $_SERVER['REDIRECT_URL'];
$internal_server_error = (http_response_code() >= 500);
}
else if (isset($_SERVER['REQUEST_URI']))
{
$relative_path = $_SERVER['REQUEST_URI'];
}
ErrorPage::GenerateErrorPage($internal_server_error, $relative_path);
?>
Короче говоря, он получает код состояния HTTP от Apache через http_response_code()и просто разделите код состояния на две категории: внутренняя ошибка сервера и не внутренняя ошибка сервера. Затем он передает категорию в ErrorPage::GenerateErrorPage() который фактически генерирует содержимое страницы ошибки.
In ErrorPage::GenerateErrorPage(), Я делаю примерно так:
<?php
http_response_code($internal_server_error ? 500 : 404);
?>
в начале функции, чтобы не было раздражающих «уже отправленных заголовков». Эта функция сгенерирует полностью функциональную страницу ошибки с правильным (или, по крайней мере, тем, что мы ожидали) кодом состояния HTTP. После установки кода состояния HTTP, как вы можете догадаться, одно из двух подготовленных материалов будет сгенерировано следующими кодами php, один для 500, другой для 404.
А теперь вернемся к твоему вопросу.
Вы хотите вызвать ту же страницу ошибки, что и Apache, и теперь вы можете просто вызвать ErrorPage::GenerateErrorPage() откуда угодно, при условии, что вы укажете правильные параметры (TRUE для 500, FALSE для 404 в моем случае).
Очевидно, потому что страницы ошибок Apache генерируются одной и той же функцией ErrorPage::GenerateErrorPage(), мы можем гарантировать, что то, что вы запускаете, где бы вы ни находились, соответствует вашим ожиданиям от страниц ошибок Apache.
Вот мой пример триггерной страницы:
<?php
ob_start();
require_once("error_page.php");
try
{
// Actual contents go here
phpInfo();
throw new Exception('test exception');
}
catch (Exception $e)
{
ob_clean();
ErrorPage::GenerateErrorPage(TRUE);
ob_end_flush();
exit();
}
ob_end_flush();
?>
Причина, по которой я использую ob_start() и ob_clean() заключается в том, что таким образом я могу очистить любой вывод до того, как возникнет исключение, и отправить чистую страницу 500 Internal Server Error, которая выглядит точно так же, как Apache, без содержимого на странице триггера (phpInfo() в этом случае). ob_start() и ob_clean() Также убедитесь, что не будет «уже отправленных заголовков», потому что ничего не будет отправлено, если вы не позвоните ob_end_flush().
Приведенное выше решение является выводом из того, что я исследовал в эти дни. Пока что для меня это хорошо, но я не уверен, что это правильный способ сделать это. Любые комментарии, вопросы, мысли, предложения и улучшения приветствуются.
Error pages are served up via .HTACCESS, if you are using Apache you would use the ErrorDocument directive and add the status and URL to it.
So it would look like this in your .htaccess file:
ErrorDocument 401 http://yourwebsite.com/error-401
ErrorDocument 403 http://yourwebsite.com/error-403
ErrorDocument 500 http://yourwebsite.com/error-500
You could use the following function below. This will dynamically add what is needed to the HTACCESS file for you or you could manually do it.
1. Add Pages:
You would then need to go into your Dashboard and create the Pages like any normal page (‘Dashboard’ > ‘Pages’ > ‘New’). They can be titled what ever you wish, just make sure the slug is the same as in the function below (Slug: error-401, error-403, error-404, error-500). Also you can use page template to create whatever layout and style you want for these specific pages. Follow WordPress Codex instructions for this.
2. Add Function:
// Create Custom Error Pages in WordPress using HTACCESS
function royal_custom_error_pages() {
// Get HTACCESS path & dynamic website url
$htaccess_file = '.htaccess';
$website_url = get_bloginfo('url').'/';
// Check & prevent writing error pages more than once
$check_file = file_get_contents($htaccess_file);
$this_string = '# BEGIN WordPress Error Pages';
if( strpos( $check_file, $this_string ) === false) {
// Setup Error page locations dynamically
$error_pages .= PHP_EOL. PHP_EOL . '# BEGIN WordPress Error Pages'. PHP_EOL. PHP_EOL;
$error_pages .= 'ErrorDocument 401 '.$website_url.'error-401'.PHP_EOL;
$error_pages .= 'ErrorDocument 403 '.$website_url.'error-403'.PHP_EOL;
$error_pages .= 'ErrorDocument 404 '.$website_url.'error-404'.PHP_EOL;
$error_pages .= 'ErrorDocument 500 '.$website_url.'error-500'.PHP_EOL;
$error_pages .= PHP_EOL. '# END WordPress Error Pages'. PHP_EOL;
// Write the error page locations to HTACCESS
$htaccess = fopen( $htaccess_file, 'a+');
fwrite( $htaccess, $error_pages );
fclose($htaccess);
}
}
add_action('init','royal_custom_error_pages'); // This will run the function everytime, not ideal!
// register_activation_hook( __FILE__, 'royal_custom_error_pages' ); // Using a plugin, runs only once!
NB!! NOTES ON THE ABOVE FUNCTION
When moving your website or changing URL structure
The thing to remember with the above function is although it will check to see if the ErrorDocument directives already exist before writing them to your HTACCESS file it will not rewrite the ErrorDocument directives should you change or move your blog to reflect the updated page locations. You would need to delete the existing ErrorDocument directives in your HTACCESS file first and then rerun this function to create the new directives.
Correct Hook to fire the function ONLY ONCE
The other thing to note is this function, using the init action will run every time your pages load which is super unnecessary and wasteful so I would suggest adding it to a plugin and using the register_activation_hook rather so it only fires once on plugin activation
File Permissions
Also it is imperative that your .htaccess is writable when using the above function, so make sure it has the correct file permissions, something like CHMOD777.