PHP: проверка ошибок арифметики через error_get_last и эмуляция error_clear_last в PHP5
Как минимум, при любом арифметическом вычислении на PHP неплохо бы проверить:
- не возвращено ли "не число" - функцией is_
nan
; - не возвращена ли "бесконечность" - функцией
is_infinite
; - не было ли иной ошибки при вычислении - функцией
error_get_last
.
В переменные $n1
, $n2
, $n3
занесём тестовые величины - 10 в тысячной степени (обязана проинтерпретироваться как бесконечность), ноль и строку (вместо числа) соответственно.
С помощью массива $operations
подготовим примеры, которые будут решаться функцией eval
- в данном случае это безопасно, так как решаемые выражения находятся только в коде, но не зависят от действий пользователя.
Массив $errors
содержит номера и строковые идентификаторы ошибок PHP, они описаны, например, здесь.
Стандартная обработка последней ошибки PHP реализована с помощью функции error_get_last.
К сожалению, сбросить предыдущее состояние ошибки можно будет только в PHP7 функцией error_clear_last. В PHP5 можно вместо неё только эмулировать код вида
set_error_handler('var_dump', 0); @$undef_var; restore_error_handler();
После этих 3 строк error_get_last
будет, по крайней мере, в известном состоянии "Undefined variable: undef_var
", что и использовано в коде.
Вот полный листинг примера:
<meta charset=utf-8> <?php error_reporting (E_ERROR); $n1 = 1e1000; $n2 = 0; $n3 = 'str'; $nums = array ('n1','n2','n3'); echo '<p>Тестовые значения:'; foreach ($nums as $num) echo "<br>$num=${$num}"; echo '</p>'; $operations = array ( "\$result = \$n1 / \$n2;", "\$result = \$n1 * \$n1;", "\$result = pow(\$n2,\$n2);", "\$result = \$n2 + \$n3;" ); $errors = array ( '1'=>'E_ERROR', '2'=>'E_WARNING', '4'=>'E_PARSE', '8'=>'E_NOTICE', '16'=>'E_CORE_ERROR', '32'=>'E_CORE_WARNING', '64'=>'E_COMPILE_ERROR', '128'=>'E_COMPILE_WARNING', '256'=>'E_USER_ERROR', '512'=>'E_USER_WARNING', '1024'=>'E_USER_NOTICE', '2048'=>'E_STRICT', '4096'=>'E_RECOVERABLE_ERROR', '8192'=>'E_DEPRECATED', '16384'=>'E_USER_DEPRECATED', '32767'=>'E_ALL' ); foreach ($operations as $op) { set_error_handler('var_dump', 0); @$undef_var; restore_error_handler(); eval ($op); $error = error_get_last(); echo '<p>Операция: '.stripslashes($op); if (is_nan($result)) echo '<br>Получено не число'; else if (is_infinite($result)) echo '<br>Получена бесконечность'; else if (!empty($error)) { echo '<br>Тип ошибки: номер '.$error['type'].', значение "'. $errors[$error['type']].'"'. '<br>Системное сообщение: '. ($error['message'] == 'Undefined variable: undef_var' ? 'не определено' : $error['message']). '<br>Файл: '.$error['file']. '<br>Номер строки: '.$error['line']; } echo '</p>'; } ?>
Результат выполнения этого примера в Denwer на локалхосте (оригинальный вывод - в Юникоде):
Тестовые значения: n1=INF n2=0 n3=str Операция: $result = $n1 / $n2; Тип ошибки: номер 2, значение "E_WARNING" Системное сообщение: Division by zero Файл: Z:\home\localhost\www\error_get_last.php(29) : eval()'d code Номер строки: 1 Операция: $result = $n1 * $n1; Получена бесконечность Операция: $result = pow($n2,$n2); Тип ошибки: номер 8, значение "E_NOTICE" Системное сообщение: не определено Файл: Z:\home\localhost\www\error_get_last.php Номер строки: 27 Операция: $result = $n2 + $n3; Тип ошибки: номер 8, значение "E_NOTICE" Системное сообщение: не определено Файл: Z:\home\localhost\www\error_get_last.php Номер строки: 27
16.09.2016, 20:54 [4710 просмотров]