Evaluate Arithmetic Strings

I was recently working on a finance ledger project which required users to be able to enter transaction splits. I wanted them to be able to do math in the actual split amount fields instead of having to load up a separate calculator. So, I decided to harness the power of PHP's eval function and now make an Ajax call from the form whenever the split amount began with an equals sign.

I didn't include all of that here, but here's the one core function that I used. Before I thought of using eval, I was trying to recreate the wheel on my own and it quickly got too complicated. There are obviously lots of security concerns with eval, but by stripping out all of the non-numeric and operation characters with regex, they are mitigated.

1.   getvarclean('string');
2.   if ($string) {
3.   	$string = trim($string);
4.   	$result = calculate_string($string);
5.   	if ($GLOBALS['equation'] !== false) { echo '<p><b>Equation:</b> '.$GLOBALS['equation'].'</p>'; }
6.   	if ($result !== false) { echo '<p><b>Result:</b> '.round($result,6).'</p>'; }
7.   	if ($GLOBALS['error']) { echo '<p class="alert">Error: '.$GLOBALS['error'].'</p>'; }
8.   }
10.  echo '<form action="'.$GLOBAL['ip']['self'].'" method="post">';
11.  echo '<p><input type="text" class="text" name="string" value="'.htmlspecialchars($string).'" size="50" /> <input type="submit" value="Calculate" class="button" /></p>';
12.  echo '</form>';
14.  function calculate_string($string) {
15.  	$GLOBALS['error'] = false;
16.  	$string = preg_replace('/[^0-9\.\*\/\+\(\)-]/','',$string);
17.  	$string = trim($string);
18.  	$s = array('+','-','/','*');
19.  	$r = array(' + ',' - ',' / ',' * ');
20.  	$GLOBALS['equation'] = str_replace($s,$r,$string);
21.  	if ($string !== '') {
22.  		@eval('$result = '.$string.'; return true;') or ($GLOBALS['error'] = 'Could not evaluate equation.');
23.  		return $result;
24.  	} else {
25.  		$GLOBALS['error'] = 'Equation does not contain any numeric characters.';
26.  		return false;
27.  	}
28.  }

Here's a working example. The code above is snagged directly from that page. Check it out.

Any questions? Suggestions? Stick them in the comments below.

Leave a Comment

Name and email are required. Your email will not be published.

This post was published on December 23rd, 2011 by Robert James Reese in PHP. Before using any of the code or other content in this post, you must read and agree to our Terms & Conditions.