БлогNot. PHP: проверка ошибок арифметики через error_get_last и эмуляция error_clear_last...

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 [4603 просмотра]


теги: ошибка php

К этой статье пока нет комментариев, Ваш будет первым