обработка ошибок — определение разницы между error_reporting (0) и предварительно ожидаемым @ в переполнении стека

Написав собственный обработчик ошибок для системы PHP, я пытаюсь выяснить, как определить, существует ли уровень сообщений об ошибках (который можно получить с помощью Отчет об ошибках()) было глобально установлено на Off (0) или было отключено для этой линии только с помощью @ префикс

В настоящее время проблема заключается в том, что в обоих случаях функция error_reporting () возвращает 0

Обновление № 1

К сожалению, этот пример не работает для PHP 5.3.3 на CentOS 6.8, так как функция ini_get () возвращает то же значение, что и error_reporting ()

function errhandle($errno, $errstr, $errfile, $errline) {
if (error_reporting() === 0 && error_reporting() === (int)ini_get('error_reporting')) {
echo 'error_reporting(0) was used';
} else if (error_reporting() === 0 && error_reporting() !== (int)ini_get('error_reporting')) {
echo '@ was used';
}
}

set_error_handler('errhandle');

echo error_reporting()."\n";
echo @$arr['name'];

// Prints
22527
error_reporting(0) was used

1

Решение

В дополнение к error_reporting()Вы также можете проверить уровень сообщений об ошибках с помощью ini_get('error_reporting'), Теоретически это похоже, но есть тонкое отличие, которое делает его ценным для того, что вы пытаетесь сделать.

Если сообщение об ошибке было отключено глобально с error_reporting(0) затем ini_get('error_reporting') вернет строку 0, Но если сообщение об ошибке было оставлено в покое, а в строке был указан префикс @, он вернет ненулевое значение (значение существующей директивы INI).

Таким образом, вы можете сравнить 2 значения и точно определить, что произошло:

if (error_reporting() === 0 && error_reporting() === (int)ini_get('error_reporting')) {
echo 'error_reporting(0) was used';
} else if (error_reporting() === 0 && error_reporting() !== (int)ini_get('error_reporting')) {
echo '@ was used';
}

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

Протестировано локально на моем PHP 7.1.2 (CLI на Windows).


Обновление № 1

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

Если вы следуете примеру из документации PHP для set_error_handler, тогда сигнатура функции для вашего пользовательского обработчика ошибок, вероятно, выглядит так:

function myErrorHandler($errno, $errstr, $errfile, $errline)

Другими словами, у вас есть файл и номер строки, где произошла ошибка. Вы можете использовать эту информацию, чтобы открыть сам файл, посмотреть на номер этой строки, разобрать токены и найти @ персонаж. Код будет выглядеть так:

function myErrorHandler($errno, $errstr, $errfile, $errline) {
$errfileContents = file($errfile);
$errlineContents = $errfileContents[$errline - 1];
$tokens = token_get_all('<?php ' . $errlineContents . ' ?>');
if (error_reporting() === 0) {
if (in_array('@', $tokens)){
echo '@ was used';
} else {
echo 'error_reporting(0) was used';
}
}
}

Очевидно, что вы можете расширить это условие, проверив, использовались ли оба метода или ни один из них.

В любом случае, это некрасиво, но у меня работает на моем PHP 5.6.6 (CLI в Windows).

2

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector