ARTICLE AD BOX
I realize this is an old question, but it is relevant today and I don't really like the answers here.
The proper way to fix this, is by actually evaluating the expression yourself - that is, by parsing the expression, then evaluating it step by step, instead of by transpiling it to PHP. This can be done using the https://en.wikipedia.org/wiki/Shunting-yard_algorithm.
I wrote the following implementation, but I haven't tested it. It's based on the above Wikipedia article. There is no support for right-associative operators, so it's slightly simplified.
// You may need to do a better parsing than this to tokenize your expression. // In PHP, you could for example use token_get_all() $formula = explode(' ', 'foo + bar * ( baz / ( foz - bak ) )');; $queue = array(); $operators = array(); $precedence = array('-' => 2, '+' => 2, '/' => 3, '*' => 3, '^' => 4); $rightAssoc = array('^'); $variables = array('foo' => $foo, 'bar' => $bar, 'baz' => $baz, 'foz' => $foz, 'bak' => $bak); foreach($formula as $token) { if(isset($variables[$token])) { $queue[] = $variables[$token]; } else if(isset($precedence[$token])) { // This is an operator while( sizeof($operators) > 0 && $operators[sizeof($operators)-1] != '(' && ( $precedence[$operators[sizeof($operators)-1]] > $precedence[$token] || ( $precedence[$operators[sizeof($operators)-1]] == $precedence[$token] && !in_array($operators[sizeof($operators)-1], $rightAssoc) ) ) ) $queue[] = array_pop($operators); $operators[] = $token; } else if($token == '(') { $operators[] = '('; } else if($token == ')') { while($operators[sizeof($operators)-1] != '(') { $queue[] = array_pop($operators); } array_pop($operators); } else if($token == ')') { while($operators[sizeof($operators)-1] != ')') { $queue[] = array_pop($operators); } if(null === array_pop($operators)) throw new \Exception("Mismatched parentheses"); } $queue = array_merge($queue, array_reverse($operators)); $stack = array(); foreach($queue as $token) { if(is_numeric($token)) $stack[] = $token; else switch($token) { case '+' : $stack[] = array_pop($stack) + array_pop($stack); break; case '-' : // Popped variables come in reverse, so... $stack[] = -array_pop($stack) + array_pop($stack); break; case '*' : $stack[] = array_pop($stack) * array_pop($stack); break; case '/' : $b = array_pop($stack); $a = array_pop($stack); if($b == 0) throw new \Exception("Division by zero"); $stack[] = $a / $b; break; } } echo "The result from the calculation is ".array_pop($stack)."\n";In your particular case
Even though I would prefer the Shunting Yard solution - if I still decided to go for an eval()-version, I would create a custom_division($leftHandSide, $rightHandSide) method, that throws an exception. This code:
eval("$foo + $bar * ( $baz / ( $foz - $bak ) )");becomes
function custom_division($a, $b) { if($b == 0) throw Exception("Div by 0"); } eval("$foo + $bar * ( custom_division( $baz, ( $foz - $bak ) )");