40

動的に作成する必要がある大きな数式があります。たとえば、「何か」を解析すると、結果は次のような文字列になります"$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";

しかし、うまくいきません。では、ゼロ除算が発生したときにアプリケーションがクラッシュしないようにするにはどうすればよいでしょうか?

編集:

まず、明確にしたいことがあります。式は動的に構築されるため、分母がゼロの場合は評価できません。では、Mark Ba​​ker のコメントについて、例を挙げましょう。私のパーサーは次のようなものを構築できます:

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

パーサーは、変数の値を気にせずに文字列を段階的に構築します...したがって、この場合$foz == $bak、実際にゼロによる除算がある場合: $baz / ( 0 ).

一方、ピートが提案したように、私は試しました:

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

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

しかし、それは何も印刷しません。

4

14 に答える 14

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

評価された式内でユーザー入力を使用している場合に非常に危険な eval を使用するのではなく、 PHPClasses で evalmath などの適切なパーサーを使用しないでください

于 2010-06-18T15:44:34.540 に答える
13

エラーが発生した場合に例外をスローするようにエラーハンドラーを設定する必要があります。

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();
于 2015-02-02T15:56:58.653 に答える
6

別の解決策は次のとおりです。

<?php

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

set_error_handler('e');

eval('echo 1/0;');

見るset_error_handler()

于 2010-06-18T15:47:45.173 に答える
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

これらを「キャッチ」したい場合は、ゼロ除算エラーを検出し、それらに対して何らかの処理を行うカスタム エラー ハンドラを設定する必要があります。残念ながら、カスタム エラー ハンドラはすべてを網羅するものです。つまり、他のすべてのエラーに対して適切な処理を行うコードを記述する必要もあります。

于 2010-06-18T16:23:44.443 に答える
2
if(@eval("\$result = $expresion;")===FALSE){
  $result=0;
}

ただし、ゼロ除算エラーをキャッチするだけではありません。

于 2010-06-18T15:45:18.730 に答える
2

@(エラー制御演算子)を使用します。これは、エラーが発生した場合に警告を出力しないように php に指示します。

eval("\$result = @($expresion);");
if ($result == 0) {
    // do division by zero handling 
} else {
    // it's all good
}
于 2010-06-18T15:53:25.740 に答える
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;
}
于 2010-08-22T11:48:38.353 に答える
2

私もこれに苦労してきましたset_error_handler.おそらくPHPのバージョンの違いに基づいて、解決策はうまくいきませんでした.

私にとっての解決策は、シャットダウン時にエラーを検出しようとすることでした:

// Since set_error_handler doesn't catch Fatal errors, we do this
function shutdown()
{
    $lastError = error_get_last();
    if (!empty($lastError)) {
        $GLOBALS['logger']->debug(null, $lastError);
    }
}
register_shutdown_function('shutdown');

0 による除算が によって処理されるのではなくシャットダウンされる理由はわかりませんが、これにより、set_error_handler静かに死ぬだけでそれを乗り越えることができました。

于 2016-12-12T21:54:10.760 に答える
1

問題:

b=1; c=0; a=b/c; // Error Divide by zero

簡単な解決策:

if(c!=0) a=b/c;
else // error handling
于 2015-11-19T15:06:53.770 に答える