У меня есть сценарий шлюза, который возвращает JSON обратно клиенту. В сценарии я использую set_error_handler, чтобы ловить ошибки и все еще иметь отформатированный возврат.
Он подвержен ошибкам «Разрешенные размеры памяти», а не увеличивает ограничение памяти с помощью чего-то вроде ini_set ('memory_limit', '19T') , я просто хочу вернуть, что пользователь должен попробовать что-то еще, потому что он использовал много Память.
Есть ли хорошие способы уловить фатальные ошибки?
Как следует из этого ответа , вы можете использовать register_shutdown_function()
для регистрации обратного вызова, который будет проверять error_get_last()
.
Вам все равно придется управлять выходом, генерируемым из-за нарушения кода, либо с помощью оператора @
( shut up ), либо ini_set('display_errors', false)
ini_set('display_errors', false); error_reporting(-1); set_error_handler(function($code, $string, $file, $line){ throw new ErrorException($string, null, $code, $file, $line); }); register_shutdown_function(function(){ $error = error_get_last(); if(null !== $error) { echo 'Caught at shutdown'; } }); try { while(true) { $data .= str_repeat('#', PHP_INT_MAX); } } catch(\Exception $exception) { echo 'Caught in try/catch'; }
вini_set('display_errors', false); error_reporting(-1); set_error_handler(function($code, $string, $file, $line){ throw new ErrorException($string, null, $code, $file, $line); }); register_shutdown_function(function(){ $error = error_get_last(); if(null !== $error) { echo 'Caught at shutdown'; } }); try { while(true) { $data .= str_repeat('#', PHP_INT_MAX); } } catch(\Exception $exception) { echo 'Caught in try/catch'; }
При запуске эти выходы Caught at shutdown
. К сожалению, ErrorException
исключения ErrorException
не вызывается, потому что фатальная ошибка запускает завершение скрипта, впоследствии попадая только в функцию выключения.
Вы можете проверить массив $error
в функции выключения для получения подробной информации о причине и ответить соответствующим образом. Одно предложение может повторить запрос обратно на ваше веб-приложение ( на другом адресе или с разными параметрами ) и вернуть захваченный ответ.
Я рекомендую сохранять error_reporting()
high ( значение -1
), хотя и использовать ( как другие предложили ) обработку ошибок для всего остального с помощью set_error_handler()
и ErrorException
.
Если вам необходимо выполнить бизнес-код при возникновении этой ошибки (ведение журнала, резервное копирование контекста для будущих отладок, отправка по электронной почте или тому подобное), регистрации функции выключения недостаточно: вы должны освободить память в некотором роде.
Одним из решений является выделение некоторой аварийной памяти:
public function initErrorHandler() { // This storage is freed on error (case of allowed memory exhausted) $this->memory = str_repeat('*', 1024 * 1024); register_shutdown_function(function() { $this->memory = null; if ((!is_null($err = error_get_last())) && (!in_array($err['type'], array (E_NOTICE, E_WARNING)))) { // $this->emergencyMethod($err); } }); return $this; }
вы можете получить размер памяти, уже потребляемой процессом, используя эту функцию. memory_get_peak_usage документация находится по адресу http://www.php.net/manual/en/function.memory-get-peak-usage.php. Я думаю, что это быть проще, если бы вы могли добавить условие для перенаправления или остановки процесса до того, как этот процесс почти достигнет предела памяти. 🙂