исключение — PHP, как отловить деление на ноль?

У меня есть большое математическое выражение, которое должно быть создано динамически. Например, после того, как я проанализировал «что-то», результатом будет строка вроде: "$foo+$bar/$baz";,

Итак, для вычисления результата этого выражения я использую eval функция … как то так:

eval("\$result = $expresion;");
echo "The result is: $result";

Проблема здесь в том, что иногда я получаю ошибки, которые говорят, что было деление на ноль, и я не знаю, как отловить это исключение. Я пробовал такие вещи, как:

eval("try{\$result = $expresion;}catch(Exception \$e){\$result = 0;}");
echo "The result is: $result";

Или же:

try{
eval("\$result = $expresion;");
}
catch(Exception $e){
$result = 0;
}
echo "The result is: $result";

Но это не работает. Итак, как я могу избежать сбоя моего приложения при делении на ноль?

Редактировать:

Во-первых, я хочу кое-что прояснить: выражение строится динамически, поэтому я не могу просто вычислить, если знаменатель равен нулю. Итак … что касается комментария Марка Бейкера, позвольте мне привести вам пример. Мой парсер может построить что-то вроде этого:

"$foo + $bar * ( $baz / ( $foz - $bak ) )"

Парсер строит строку шаг за шагом, не беспокоясь о значении vars … так что в этом случае, если $foz == $bak на самом деле деление на ноль: $baz / ( 0 ),

С другой стороны, как предположил Пит, я попытался:

<?php
$a = 5;
$b = 0;

if(@eval(" try{ \$res = $a/$b; } catch(Exception \$e){}") === FALSE)
$res = 0;
echo "$res\n";
?>

Но это ничего не печатает.

25

Решение

if ($baz == 0.0) {
echo 'Divisor is 0';
} else {
...
}

Вместо использования eval, что очень опасно, если вы используете пользовательский ввод в выражении evalled, почему бы не использовать правильный синтаксический анализатор, такой как Evalmath на PHPClasses, и который вызывает чистое исключение при делении на ноль

16

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

Вот еще одно решение:

<?php

function e($errno, $errstr, $errfile, $errline) {
print "caught!\n";
}

set_error_handler('e');

eval('echo 1/0;');

Увидеть set_error_handler()

6

Вам просто нужно установить обработчик ошибок для выдачи исключения в случае ошибок:

set_error_handler(function () {
throw new Exception('Ach!');
});

try {
$result = 4 / 0;
} catch( Exception $e ){
echo "Divide by zero, I don't fear you!".PHP_EOL;
$result = 0;
}

restore_error_handler();
4

Как уже упоминалось, попробуйте найти решение, которое позволит вам проверить, равен ли знаменатель 0.

Поскольку этот совет кажется бесполезным для вашей цели, вот небольшая справка по обработке ошибок PHP.

Ранние версии PHP не имели исключений. Вместо этого были выданы сообщения об ошибках различных уровней (Уведомления, Предупреждения и т. Д.). Неустранимая ошибка останавливает выполнение.

PHP5 принес исключения в таблицу, и более новые библиотеки, предоставляемые PHP (PDO), будут генерировать исключения, когда происходят плохие / неожиданные вещи. Однако базовая кодовая база НЕ была переписана для использования исключения. Основные функции и операции по-прежнему опираются на старую систему ошибок.

Когда вы делите на 0, вы получаете предупреждение, а не исключение

PHP Warning:  Division by zero in /foo/baz/bar/test.php(2) : eval()'d code on line 1
PHP Stack trace:
PHP   1. {main}() /foo/baz/bar/test.php:0
PHP   2. eval() /foo/baz/bar/test.php:2

Если вы хотите «поймать» их, вам нужно установить собственный обработчик ошибок это обнаружит деление на ноль ошибок и что-то с ними сделает. К сожалению, пользовательские обработчики ошибок — это главное, что означает, что вам также нужно написать некоторый код, чтобы сделать что-то соответствующее со всеми другими ошибками.

3

На PHP7 вы можете использовать DivisionByZeroError

try {
echo 1/0;
}
catch(DivisionByZeroError $e){
echo "got $e";
}
3
if(@eval("\$result = $expresion;")===FALSE){
$result=0;
}

Не поймать просто делить на 0 ошибок.

2

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

function eval_expression($expression)
{
ob_start();
eval('echo (' .  $expression . ');');
$result = ob_get_contents();
ob_end_clean();
if (strpos($result, 'Warning: Division by zero')!==false)
{
throw new Exception('Division by zero');
}
else return (float)$result;
}
2

Вы можете просто поймать DivisionByZeroError в PHP> = 7

Увидеть http://php.net/manual/en/class.divisionbyzeroerror.php

2
По вопросам рекламы [email protected]