Отображение пользовательской страницы ошибок в PHP для ошибок, которые не могут быть обнаружены set_error_handler - PullRequest
2 голосов
/ 15 июля 2010

Я хотел бы иметь возможность отказаться от частично отрендеренной страницы и показать страницу ошибки в PHP.

Я уже знаю о set_error_handler () , но может отлавливать только определенные типы ошибок .Я хотел бы знать, как показать страницу с ошибкой, когда возникает тип ошибки, который не может быть перехвачен set_error_handler () .

К сожалению, кажется, что следующий код, когдаработать с PHP 5.3.2 на Apache 2.2, не делает то, что я ожидал:

<?php

// Start the output buffer
ob_start();

// Output something into the buffer.
// I only want this to be displayed if I call one of the 
// ob_flush functions or echo the buffer myself later.
echo "yep";

// Call a function I know not to exist in order to raise 
// an error which cannot be trapped by set_error_handler() 
// and would, if display_errors was On, output "Fatal 
// error: Call to undefined function fwee()..." 
function_which_does_not_exist();

// This will never be executed.
$out = ob_get_clean();

Вывод скрипта:

yep

Принимая во внимание, чтоожидать, что он ничего не выводит (или выводит информацию об ошибке и только информацию об ошибке, если display_errors () включен).

Я подтвердил с помощью LiveHTTPHeaders, что PHP 5.3.2 действительно отправляет 500 ошибку браузеру, когда display_errors выключен(и 200, когда он включен) с использованием версии apache, поставляемой MacPorts, но он только плюет на 200 с при использовании PHP 5.3.1 на XAMPP.

Я попытался установить ErrorDocument 500 "test" в конфигурации apache(подтверждено, что он работает так же, как и для 404), но PHP никогда не показывает пользовательскую ошибку, даже когда все содержимое скрипта просто header('HTTP/1.1 500 Internal Server Error');

Я не уверен, что еще нужно сделать, чтобы сделатьсуЕсли частично визуализированная страница заменена простой ошибкой.

Я также могу подтвердить, что это происходит в среде Yii.Если я отредактирую представление для страницы "about" в демо-версии блога, добавив строку, которая будет читать <?php echo function_which_does_not_exist() ?>, я получу частично визуализированную страницу.

Ответы [ 4 ]

1 голос
/ 22 июля 2010

Вы можете передать ob_start имя функции обратного вызова, которая выполняется до сброса вывода в ob_get_clean ().

Эта функция обратного вызова может выполняться, даже если на странице произошла ошибка.

Таким образом, вы могли бы сделать что-то вроде этого:

<?php
$endReached = 0;

function outpu_cb($buffer) {
  global $endReached;

  if ($endReached) return $buffer;
  else return 'Your error message';
}

// Start the output buffer
ob_start('outpu_cb');

// Output something into the buffer.
// I only want this to be displayed if I call one of the
// ob_flush functions or echo the buffer myself later.
echo "yep";

// Call a function I know not to exist in order to raise
// an error which cannot be trapped by set_error_handler()
// and would, if display_errors was On, output "Fatal
// error: Call to undefined function fwee()..."
function_which_does_not_exist();

// This will never be executed.
$endReached = 1;
echo ob_get_clean();
?>
0 голосов
/ 19 декабря 2012

Старый вопрос, но для протокола я бы предложил избегать этой проблемы, а не решать ее.

Мой собственный подход состоит в том, чтобы построить ответ в объекте ответа, а не отображать его по мере продвижения, и выводить результат только после обработки полного ответа без ошибок.Для этого требуется система шаблонов, которая анализирует ваш шаблон и встраивает ваш ответ в строку, в отличие от классического шаблона PHP, отражающего вывод ваших заполнителей.

Таким образом, вы полностью избегаете грубого управления PHP в кэше выводасостояния ошибки.

0 голосов
/ 23 июля 2010

Если вы говорите об E_FATAL или других подобных ошибках, то вы можете отловить их с помощью специального обработчика ошибок, используя set_error_handler ().

Все, что вам нужно добавить, - это функция отключения.1005 * Взгляните на http://micromvc.com или http://kohanaphp.com/, чтобы увидеть, как это делается.

0 голосов
/ 15 июля 2010

Я думаю, что единственный правильный способ сделать это - использовать правильную буферизацию вывода, чем вам не нужно полагаться на конкретный веб-сервер или поведение браузера.

Лучше всего вы будете использовать инфраструктуру MVC для обработкиэто для тебя.Все выходные данные буферизуются до тех пор, пока не будут отключены все системы, поэтому при возникновении ошибки вы можете выбрать другой маршрут, очистить текущий буфер и отобразить несколько приятных сообщений об ошибках.

Вы также можете использовать семейство функций ob _ * (),

  • Вы должны вызвать ob_start () как самое первое в вашем скрипте (ну, прежде чем сгенерируется любой вывод)
  • Установить обработчик ошибок для полученияошибки
  • При возникновении ошибки очистите буфер и перенаправьте логику приложения, чтобы отобразить приятное сообщение об ошибке
...