Обработка ошибки сервера 5XX в ответе, а не заголовков, в PHP REST api [duplicate]

Если вы недавно обновили свою версию php, вы можете забыть перезагрузить службу веб-сервера.

51
задан A.N.M. Saiful Islam 14 December 2009 в 11:57
поделиться

6 ответов

Простой ответ: вы не можете. См. Руководство :

Следующие типы ошибок не могут обрабатываться с помощью определенной пользователем функции: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING и большая часть E_STRICT поднятый в файле, где вызывается set_error_handler ().

Для каждой другой ошибки вы можете использовать set_error_handler()

EDIT:

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

Используя register_shutdown_function, вы не можете обрабатывать ошибку из кода, в котором она была так что код все равно перестанет работать в точке, где происходит ошибка. Однако вы можете представить пользователю сообщение об ошибке вместо белой страницы, но вы не можете, например, отбросить все, что ваш код сделал до сбоя.

26
ответ дан Dan Soap 26 August 2018 в 08:10
поделиться
  • 1
    Фактически вы можете обрабатывать эти ошибки с помощью определенной пользователем функции. Все, что вам нужно сделать, это определить register_shutdown_function. См. Мой ответ ниже для рабочего примера, который я реализовал на своем веб-сайте. – jdias 20 September 2011 в 19:32
  • 2
    Да, ты можешь. Однако есть некоторые недостатки: см. Мое редактирование выше – Dan Soap 30 September 2011 в 21:59
  • 3
    Спасибо за обновление. На самом деле вы можете сделать больше, чем представить пользователю сообщение об ошибке. Вы можете регистрировать сведения об ошибке, включая переменные, которые были установлены во время возникновения ошибки. Многие люди, которые используют общий хостинг, не имеют доступа к журналам Apache, например. Используя эту функцию, они смогут регистрировать критические ошибки и обращаться к ним. Кроме того, вы можете попытаться восстановить транзакции. Например, если ошибка возникла, когда пользователь пытался разместить заказ, вы можете сбросить все детали заказа в журнале или электронной почте и попытаться восстановить его в автономном режиме. – jdias 30 September 2011 в 22:50
  • 4
    На практике практически единственная разница между фатальной ошибкой и неожиданной нефатальной ошибкой заключается в том, что вы не можете получить трассировку стека для первого. – Tgr 2 August 2012 в 11:02
  • 5
    Или вы можете & quot; обрабатывать & quot; их через приложение, подобное NewRelic, которое позволяет вам их захватывать, а затем активно контролировать и исправлять. Если вы просто проигнорируете их, они никогда не будут обработаны. – GL_Stephen 31 March 2014 в 19:30

Из комментариев PHP.net на странице http://www.php.net/manual/en/function.set-error-handler.php

Я понял, что несколько человек здесь упомянули, что вы не можете захватить ошибки разбора (тип 4, E_PARSE). Это неправда. Вот как я это делаю. Я надеюсь, что это помогает кому-то.

1) Создайте файл auto_prepend.php в корневом каталоге веб-сайта и добавьте следующее:

<?php 
register_shutdown_function('error_alert'); 

function error_alert() 
{ 
        if(is_null($e = error_get_last()) === false) 
        { 
                mail('your.email@example.com', 'Error from auto_prepend', print_r($e, true)); 
        } 
} 
?> 

2) Затем добавьте этот «php_value auto_prepend_file» /www/auto_prepend.php "в ваш .htaccess файл в корневом каталоге.

  • убедитесь, что вы изменили адрес электронной почты и путь к файлу.
11
ответ дан Creativehavoc 26 August 2018 в 08:10
поделиться
  • 1
    Это решение охватывает E_PARSE, E_COMPILE_ERROR и т. Д. Поэтому ответ Дэна Мына и руководство php.net ошибочны. Спасибо! – mgutt 16 February 2015 в 20:25
  • 2
    Если вы используете FastCgi, вы не можете установить значение PHP в .htaccess. Вместо этого вы используете свой локальный файл php.ini и автоматически устанавливаете auto_prepend_file = /www/auto_prepend.php – user 26 April 2016 в 06:35

Скрипт с ошибкой синтаксического разбора всегда прерывается и его нельзя обрабатывать. Поэтому, если скрипт вызывается напрямую или include / require, вы ничего не можете сделать. Но если он вызывается AJAX, flash или каким-либо другим способом, есть способ обхода ошибок синтаксического анализа.

Мне нужно было это, чтобы обрабатывать скрипт swfupload . Swfupload - это флеш-память, которая обрабатывает загрузку файлов и загружается каждый раз, она вызывает скрипт обработки PHP для обработки filedata, но нет выхода для браузера, поэтому скрипт обработки PHP нуждается в этих настройках для целей отладки:

  • предупреждения и уведомления ob_start (); в начале и сохранить содержимое в сеансе ob_get_contents (); в конце сценария обработки: это можно отобразить в браузере другим скриптом
  • фатальными ошибками register_shutdown_function (), чтобы установить сеанс с тем же трюком, что и выше
  • ob_get_contents () находится в конце скрипта обработки, и ранее была обнаружена ошибка синтаксиса, сессия не заполнена (она равна нулю). Сценарий отладки может обрабатывать его следующим образом: if(!isset($_SESSION["swfupload"])) echo "parse error";

Примечание 1 null означает is not set - isset()

4
ответ дан Jan Turoň 26 August 2018 в 08:10
поделиться

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

1) Сценарий начального / верхнего уровня, назовем его index.php, где вы храните свои пользовательские функции обработчика ошибок. Пользовательские обработчики функций ошибок должны оставаться наверху, чтобы они ломали ошибки под ними, «ниже» я имею в виду в включенных файлах.

2) Предположение, что этот верхний скрипт является ошибкой, обязательно должен быть правдой! это очень важно, вы не можете обнаружить фатальные ошибки в index.php, когда ваша функция обработчика ошибок найдена в index.php.

3) Директивы Php (также должны быть найдены в index.php) set_error_handler("myNonFatalErrorHandler"); #, чтобы поймать нефатальные ошибки register_shutdown_function('myShutdown'); # для того, чтобы улавливать фатальные ошибки ini_set('display_errors', false); #, чтобы скрыть ошибки, отображаемые пользователю по php ini_set('log_errors',FALSE); #, чтобы мы регистрировали ошибки сами себя ini_set('error_reporting', E_ALL); # Нам нравится сообщать обо всех ошибках

во время производства (если я не ошибаюсь), мы можем оставить ini_set('error_reporting', E_ALL); как есть, чтобы иметь возможность регистрировать ошибку, в то же время ini_set('display_errors', false); будет убедиться, что нет ошибки отображаются пользователю.

Что касается фактического содержимого двух функций, о которых я говорю, myNonFatalErrorHandler и myShutdown, я не размещаю подробный контент здесь, чтобы все было просто. Кроме того, другие посетители дали множество примеров. Я просто показываю очень простую идею.

function myNonFatalErrorHandler($v, $m, $f, $l, $c){
 $some_logging_var_arr1[]="format $v, $m, $f, ".$err_lvl[$l].", $c the way you like";
 //You can display the content of $some_logging_var_arr1 at the end of execution too.
}

function myShutdown()
{
  if( ($e=error_get_last())!==null ){
      $some_logging_var_arr2= "Format the way you like:". $err_level[$e['type']].$e['message'].$e['file'].$e['line'];
  }
//display $some_logging_var_arr2 now or later, e.g. from a custom session close function
}

как для $ err_lvl это может быть:

$err_lvl = array(E_ERROR=>'E_ERROR', E_CORE_ERROR=>'E_CORE_ERROR', E_COMPILE_ERROR=>'E_COMPILE_ERROR', E_USER_ERROR=>'E_USER_ERROR', E_PARSE=>'E_PARSE', E_RECOVERABLE_ERROR=>'E_RECOVERABLE_ERROR', E_WARNING=>'E_WARNING', E_CORE_WARNING=>'E_CORE_WARNING', E_COMPILE_WARNING=>'E_COMPILE_WARNING',
E_USER_WARNING=>'E_USER_WARNING', E_NOTICE=>'E_NOTICE', E_USER_NOTICE=>'E_USER_NOTICE',E_STRICT=>'E_STRICT');
4
ответ дан Melsi 26 August 2018 в 08:10
поделиться

На самом деле вы можете обрабатывать синтаксические и фатальные ошибки. Верно, что функция обработчика ошибок, которую вы определили с помощью set_error_handler (), не будет вызываться. Способ сделать это - определить функцию выключения с помощью register_shutdown_function (). Вот что я работал на своем веб-сайте:

Файл prepend.php (этот файл будет автоматически добавлен ко всем скриптам php). Ниже приведены советы по добавлению файлов в PHP.

set_error_handler("errorHandler");
register_shutdown_function("shutdownHandler");

function errorHandler($error_level, $error_message, $error_file, $error_line, $error_context)
{
$error = "lvl: " . $error_level . " | msg:" . $error_message . " | file:" . $error_file . " | ln:" . $error_line;
switch ($error_level) {
    case E_ERROR:
    case E_CORE_ERROR:
    case E_COMPILE_ERROR:
    case E_PARSE:
        mylog($error, "fatal");
        break;
    case E_USER_ERROR:
    case E_RECOVERABLE_ERROR:
        mylog($error, "error");
        break;
    case E_WARNING:
    case E_CORE_WARNING:
    case E_COMPILE_WARNING:
    case E_USER_WARNING:
        mylog($error, "warn");
        break;
    case E_NOTICE:
    case E_USER_NOTICE:
        mylog($error, "info");
        break;
    case E_STRICT:
        mylog($error, "debug");
        break;
    default:
        mylog($error, "warn");
}
}

function shutdownHandler() //will be called when php script ends.
{
$lasterror = error_get_last();
switch ($lasterror['type'])
{
    case E_ERROR:
    case E_CORE_ERROR:
    case E_COMPILE_ERROR:
    case E_USER_ERROR:
    case E_RECOVERABLE_ERROR:
    case E_CORE_WARNING:
    case E_COMPILE_WARNING:
    case E_PARSE:
        $error = "[SHUTDOWN] lvl:" . $lasterror['type'] . " | msg:" . $lasterror['message'] . " | file:" . $lasterror['file'] . " | ln:" . $lasterror['line'];
        mylog($error, "fatal");
}
}

function mylog($error, $errlvl)
{
...do whatever you want...
}

PHP вызовет функцию errorHandler (), если он обнаружит ошибку в любом из скриптов. Если ошибка заставляет скрипт немедленно отключиться, ошибка обрабатывается функцией shutdownHandler ().

Это работает на сайте, который я разрабатываю. Я еще не тестировал его на производстве. Но в настоящее время он ловит все ошибки, которые я обнаружил при разработке.

Я считаю, что существует риск перехвата одной и той же ошибки дважды, по каждой функции. Это может произойти, если ошибка, которую я обрабатываю в функции shutdownHandler (), также была обнаружена функцией errorHandler ().

TODO's:

1 - Мне нужно работать лучше log () для корректной обработки ошибок. Поскольку я все еще в разработке, я в основном регистрирую ошибку в базе данных и повторяю ее на экране.

2 - Реализация обработки ошибок для всех вызовов MySQL.

3 - Реализация обработка ошибок для моего кода javascript.

ВАЖНЫЕ ПРИМЕЧАНИЯ:

1 - Я использую следующую строку в моем php.ini, чтобы автоматически добавить вышеприведенный скрипт ко всем скриптам php:

auto_prepend_file = "/homepages/45/d301354504/htdocs/hmsee/cgi-bin/errorhandling.php"

работает хорошо.

2 - Я регистрирую и разрешаю все ошибки, включая ошибки E_STRICT. Я верю в разработку чистого кода. Во время разработки мой файл php.ini имеет следующие строки:

track_errors = 1
display_errors = 1
error_reporting = 2147483647
html_errors = 0

Когда я перехожу вживую, я изменил display_errors на 0, чтобы уменьшить риск того, что мои пользователи будут видеть уродливые сообщения об ошибках PHP.

Надеюсь, это поможет кому-то.

62
ответ дан R_User 26 August 2018 в 08:10
поделиться
  • 1
    Кажется, что не обрабатывается «Parse Errors» ... попробуйте следующее: echo & quot; Cat & quot ;; echo & quot; Dog & quot; эхо "Лев"; – Phantom007 10 May 2014 в 18:56
  • 2
    Вы должны добавить файл для обработки ошибок разбора! – Dargmuesli 24 October 2016 в 16:22
  • 3
    E_DEPRECATED и E_USER_DEPRECATED также должны быть включены в пользовательскую функцию обработчика ошибок. – Wh1T3h4Ck5 19 September 2017 в 03:38

Вы можете отслеживать эти ошибки с помощью кода следующим образом:

(Ошибки анализа могут быть обнаружены только в том случае, если они встречаются в других файлах сценария через include() или require(), или помещая этот код в auto_prepend_file, как упомянули другие ответы.)

function shutdown() {
    $isError = false;

    if ($error = error_get_last()){
    switch($error['type']){
        case E_ERROR:
        case E_CORE_ERROR:
        case E_COMPILE_ERROR:
        case E_USER_ERROR:
            $isError = true;
            break;
        }
    }

    if ($isError){
        var_dump ($error);//do whatever you need with it
    }
}

register_shutdown_function('shutdown');
29
ответ дан Simon East 26 August 2018 в 08:10
поделиться
  • 1
    Вы протестировали его? – Peter Lindqvist 14 December 2009 в 15:47
  • 2
    Да, есть способ поймать E_PARSE! Поместите функцию обработчика ошибок в index.php и включите / укажите другой файл, где должна быть логика сайта! – Lucas Batistussi 12 May 2012 в 22:59
  • 3
    Единственный способ, с помощью которого я мог предотвратить ошибки синтаксического анализа, состоял в том, чтобы включить скрипт, содержащий ошибку синтаксического анализа. – Melsi 27 April 2013 в 01:00
  • 4
    Тестирование на php 5.3 - win 7. Функция выключения НЕ вызывается при ошибках разбора. – kwolfe 17 September 2013 в 21:29
  • 5
    @LucasBatistussi вы можете объяснить? Я положил функцию обработчика ошибок в index.php & amp; затем включите его в свой скрипт, используя include(index.php). Но он все еще не может поймать ошибки синтаксического анализа (синтаксическая ошибка). Я не думаю, что это возможно, не встраивая его в php.ini. – Khurshid Alam 20 August 2014 в 19:31
Другие вопросы по тегам:

Похожие вопросы: