0

Im trying to compute a simple expression in PHP, the expression will always be the same the only change is in the operator.

Is there a simple solution to rather than duplicate the formula, just use the single expression and have the operator as a variable.

Something like..

function calc($qty, $qty_price, $max_qty, $operator_value, $operator = '-') 
{

  $operators = array(
   '+' => '+',
   '-' => '-',
   '*' => '*',
  );

  //adjust the qty if max is too large
  $fmq = ($max_qty > $qty)? $qty  : $max_qty ;


  return ( ($qty_price  . $operators[$operator] . $operator_value) * $fmq ) + ($qty - $fmq) * $qty_price;

}
2
  • 1
    You can use eval() but that's usually a bad code smell Commented Jul 20, 2013 at 3:21
  • It has crossed my mind but Id rather not use eval() Commented Jul 20, 2013 at 3:41

3 Answers 3

2

The 5.3 answer is nice, however, why not pre-calcaute $qty_price +-* $operator_value rather than repeating the whole function? It'd make the code a little more readable...

E.g.

function calc($qty, $qty_price, $max_qty, $operator_value, $operator = '-') 
{
  $qty_price_orig = $qty_price;

  switch($operator) {
      case '-':
         $qty_price -= $operator_value;
         break;
      case '+':
        $qty_price += $operator_value; 
        break;
      case '*':
         $qty_price = $qty_price * $operator_value; 
         break;


  //adjust the qty  i max is too large
  $fmq = ($max_qty > $qty)? $qty  : $max_qty ;


  return ( $qty_price * $fmq ) + ($qty - $fmq) * $qty_price_orig;

}
Sign up to request clarification or add additional context in comments.

4 Comments

Ill probably use this code for compatibility reasons. My software needs to work on both PHP 5.1 and 5.3.
you might need to adjust your formula by the way - at the moment it is multiplying ($qty - $fmq) * $qty_price_orig and then adding ( $qty_price * $fmq ). If that is desired, add brackets around the multiplier so that when you come back to edit code / someone else comes into maintain it, it's immediately obvious what you wanted it to do.
do you mean ( $qty_price * $fmq ) + ( ($qty - $fmq) * $qty_price_orig);
yup! Just means that it's immediately obvious to me what you meant the function to do. I wondered if you meant it to be ( ( $qty_price * $fmq ) + ($qty - $fmq) ) * $qty_price_orig; you see.
2

If youre using 5.3+ then just use functions as your operator values:

$operators = array(
   '+' => function (a,b) { return a+b; },
   '-' => function (a,b) { return a-b; },
   '*' => function (a,b) { return a*b; },
);

$fmq = ($max_qty > $qty)? $qty  : $max_qty ;


return ( $operators[$operator]($qty_price, $operator_value) * $fmq ) + ($qty - $fmq) * $qty_price;

If youre using < 5.3 then you can use create_function() to do much the same.

3 Comments

I didn't know we could store the function in the array, nice
I really like this solution, however I think in my case dealing with compatibility is probably more important so @stefancarlton solution may have to be the one for me
@IEnumerable: Yep, that requirement trumps ease/compactness. As long as you dont use eval youre good :-)
0

If you want to use eval() to get the job done:

<?php
$operators = array(
   '+' => '+',
   '-' => '-',
   '*' => '*',
  );

$a = 3;
$b = 4;
foreach ($operators as $op) {
    $expr = "$a ".$op." $b";
    eval("\$result=".$expr.";");
    print_r($expr." = ".$result."\n");
}
?>

However, use it with caution! Here is the official warning:

The eval() language construct is very dangerous because it allows execution of arbitrary PHP code. Its use thus is discouraged. If you have carefully verified that there is no other option than to use this construct, pay special attention not to pass any user provided data into it without properly validating it beforehand.

1 Comment

I know you gave the warning, but eval is probably the least appropriate answer even though it works given how simple the problem is.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.