1

I am trying to use an operator as a variable.

$num1 = 33;
$num2 = 44;
$operator = "+";
$answer = ($num1.$operator.$num2);

It prints "33+44" instead of 77.

Or,

$operators = array(
   "plus"=>"+", 
   "minus"=>"-",
   "times"=>"*", 
   "div"=>"/"
  );

I want to be able to use as: $answer = $num1.$operators["plus"].$num2;

How can I achieve this without using "if" statement?.

$answer = ($operator == "+") ? $num1 + $num2 : 0;

4 Answers4

4
    $num1 = 33;
    $num2 = 44;
    $operator = "+";
    eval("\$result = $num1 $operator $num2;"); 
    echo $result;

Caution 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.

sumit
  • 15,003
  • 12
  • 69
  • 110
3

On the user-land

Think about things that you're trying to achieve. Why don't create fixed-code closures? You may easily do it with:

$operators = array(
   "plus"=>function($x, $y)
   {
      return $x+$y;
   }, 
   "minus"=>function($x, $y)
   {
      return $x-$y;
   },
   "times"=>function($x, $y)
   {
      return $x*$y;
   }, 
   "div"=>function($x, $y)
   {
      return $x/$y;
   }
  );

//in PHP 5.5:
$result = $operators['plus']($num1, $num2);
//in PHP<5.5:
//$result = call_user_func_array($operators['plus'], [$num1, $num2])

Now you have two things: first, it's still dynamic code - and you may use it in expressions. Next, you're safe in terms of code evaluation - because you've defined the code by yourself. This approach also has advantage - you may define desired behavior as you wish. For instance, raise an exception for "div" operator if second operand is zero.

"Easy" way

I'll notice this only to explain why this isn't a right way. You may use eval(). It's like:

eval('$result='.$num1.$operators['plus'].$num2.';');

And then your result would be stored in $result variable. It is about "easy" way, but not "right" way. The problem is - it is unsafe. Just think about it - you're executing some code, which is dynamic. If your code has nothing to do with user input, it may be applicable - in case, if you're checking your operands and operator before. But I still recommend to think twice before applying it.

If evaluation still needed

Then I recommend to look to some existing implementations. Here are some links:

Community
  • 1
  • 1
Alma Do
  • 37,009
  • 9
  • 76
  • 105
1

You can try to use BC Math functions. This example works with php 5.5:

$num1 = 33;
$num2 = 44;
$operator = '+';
$funcs = array(
    '+' => 'bcadd',
    '-' => 'bcsub',
    '/' => 'bcdiv',
    '*' => 'bcmul',
    );

$answer = $funcs[$operator]($num1, $num2); // 77
edigu
  • 9,878
  • 5
  • 57
  • 80
0

I question why you want to pass the arithmetic operator as a string in the first place, but here's a way to do it without using an if statement:

function fancy_math($num1 = 0, $num2 = 0, $operator = '+')
{
    switch ($operator) {
        case 'minus':
        case '-':
            return $num1 - $num2;
            break;

        case 'times':
        case '*':
            return $num1 * $num2;
            break;

        case 'div':
        case '/':
            return ($num2 !== 0) ? $num1 / $num2 : 'Error: divide by zero';
            break;

        default:
            return $num1 + $num2;
            break;
    }
}

And then call it like this:

$answer = fancy_math($num1, $num2, $operator);

Note you can pass 'minus' or '-' (etc) as the $operator as it will accept both. If you don't pass an $operator it will assume 'plus' or '+' automatically.

TunaMaxx
  • 1,782
  • 12
  • 18
  • Return a string or number in case of "div"? Type-safe comparison while nowhere before types are checked? Actually, not good ideas – Alma Do Aug 18 '14 at 07:15
  • The whole thing is in the category of "not good ideas." I could have just let the potential divide by zero happen like you did. Otherwise, our two solutions attack the problem in the same fashion. Mine is dead basic and runs anywhere. Your's requires 5.5 or the clumsy call_user_func_array(). – TunaMaxx Aug 18 '14 at 07:21
  • Actually, usage of PHP<5.5 is also a bad idea – Alma Do Aug 18 '14 at 07:22
  • Yes, and it sucks to drive anything less than the current model year car too. Reality is most of the cars on the road aren't current year; most of the PHP hosts around aren't 5.5 either. – TunaMaxx Aug 18 '14 at 07:25
  • Reality is so that PHP versions have nothing to do with cars. Usage of older versions is at least non-safe. Same goes for most software. If there are no reasons to use lower versions, don't use it (and in _reality_ there are no such reasons, because BC were broken only starting from 5.2). But no matter the version. Returning string in context of numeric function is just wrong. – Alma Do Aug 18 '14 at 07:27
  • As awesome as it would be if every PHP server on the web was 5.5 and quivering to hop on 5.6 the day it is released, the reality is ~70% are all running 5.3 / 5.4 at the moment. 5.3 is hovering around 3% global adoption. http://w3techs.com/technologies/details/pl-php/5/all – TunaMaxx Aug 18 '14 at 07:34
  • This has nothing to do with "reality". Because for "real" things proper tools are needed, and, therefore, proper hostings are chosen. It's not "servers" that determine which version to run. It's people who're making the decision. And if you'll run your own VPS at least, it's not a problem. Only problem may be in BC, but, again, it's not an issue since 5.2 – Alma Do Aug 18 '14 at 07:37
  • You know what? You are right; this discussion has lost all touch with reality. You win. I can't believe how wrong I was. Thank you for showing me the light. – TunaMaxx Aug 18 '14 at 07:40