Assignment operator as a variable in php - php

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;

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

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:
Safe math calculation instead of eval()
Existing math evaluation repo (github)

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

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.

Related

Php : how to evaluate string to operator?

I have 3 variables :
$a = 5;
$b = 3
$o = "*";
The $o variable contains a string value. This value can also be "/", "+", "-".
So when I concatenate $a.$o.$b :
$result = $a.$o.$b;
echo $result;
The result is 5*3 (a string) instead of 15.
So how to convert operator string into real operator ?
You can't, you'd need to make a function or a switch statement to check each of the operators.
Read this question and its answers so you'll understand how to do it.
Actually you can do it, by using eval. But it hurts to recommend using eval, so I just give you a link to another question with a good answer: calculate math expression from a string using eval
You can use eval. For example:
eval('echo 5*3;')
will echo the number 15.
Simple, short and save solution:
$a = 5;
$b = 3
$o = "*";
$simplecalc = function($a,$b,$op) {
switch($op):
case "*":
return $a*$b;
case "+":
return $a+$b;
case "-":
return $a-$b;
case "/";
return $a/$b;
default:
return false;
endswitch;
};
$result = $simplecalc($a,$b,$o);
I believe this is what you are looking for.
$a = 5;
$b = 3;
$o = "*";
$result = eval( "echo $a$o$b;" );
echo $result;
Please note that using eval() is very dangerous, because it allows execution of arbitrary PHP code.

Is it possible to have PHP if statement with all variables?

Simple question really. I have come across an issue with work where it would be ideal to store >= <= and == into a variable to spit out into certain if statements wherever the case may be.
$numb1 = 5
$numb2 = 10
$option = >=
if($numb1 $option $numb2)
You can't put a var for testing this in a control instruction.
This will return some : syntax error, unexpected T_VARIABLE
You could use some eval() to do it, but it's not advisable.
Perhap's you could make something different with the following :
$option=$_GET['option']; // or POST or something else...
$numb1 = 5;
$numb2 = 10;
switch($option) {
case ">=":
if($numb1 >= $numb2){//someting}
break;
case "<=":
if($numb1 <= $numb2){//someting}
break;
case "==":
if($numb1 == $numb2){//someting}
break;
default://something else if there is no $option
break;
}
Or with a function like the following
function testVar($numb1,$numb2,$option)
{
// Same switch
}
Not without using eval() which is generally considered a bad idea
Doing it directly like that, will only work using eval() - Using eval is not considered good practice. The main problem being that if the eval() statements takes in user input the user can inject php into your code. That's obviously bad. Refer this thread - When is eval evil in php?
What you'd be better off doing is created a series of switch statements for all the various operations such as 'greater than', 'less than', 'equals' and so forth...
The best thing to do for this is to make a function call or object wrapper, and then call the function to achieve the same result.
Example:
$func = '__my_eq_op_';
if ($func($numb1,$numb2)) {
// Do stuff
}
The operator functions are then...
function __my_eq_op($a,$b) {
return $a == $b;
}
function __my_gte_op($a,$b) {
return $a >= $b;
}
function __my_lte_op($a,$b) {
return $a <= $b;
}
For example. So you can really just break it down into using the functions instead.
For this:
if ($x == $y)
The parser sees 6 tokens...
1) KEYWORD IF:
2) LPAREN
3) VAR X
4) EQ
5) VAR Y
6) RPAREN
The parser uses these tokens to construct the AST for the IF conditional. Your thinking needs to move away from seeing the "==" as a variable. It's an operator!

What type do arithmetic operators (+ - / *) have in PHP?

What type do arithmetic operators (+ - / *) have in PHP? I have such situation:
$argX= "1";
$argY = "2";
$operator = "+";
I want to add up two arguments using the operator in the variable. Smth like this:
$result = $argX $operator $argY;
I know that arguments are strings, so I convert them to numbers first.
$argX = $argX+0;
$argY = $argY+0;
But in what should I convert $operator to add the arguments using a value of $operator variable? How is it possible?
No, this is not possible. You cannot use expressions for operators in PHP. Operators are operators, they don't have a type. You'll have to do something like this:
switch ($operator) {
case '+' : $result = $argX + $argY; break;
case '-' : $result = $argX - $argY; break;
...
}
You could eval it, but I wouldn't recommend that.
you can't do that, however you could do
if($operator == '+')
{
//math
}
Something like:
// allowed operators
$allowed = array('+','-','/','*','%');
// check to see that operator is allowed and that the arguments are numeric
// so users can't inject cheeky stuff
if(in_array($operator, $allowed) && is_numeric($argX) && is_numeric($argY)){
eval('<?php $result = '.$argX.' '.$operator.' '.$argY.'; ?>');
}
Wouldn't a function named operator also work?
function operator($X, $Y) {
$Z = $X + $Y;
return $Z
}
$Z = operator($X,$Y);

php switch strange anomaly

I have this code where $difference=0
switch ($difference)
{
case 0<=$difference && $difference<300:
return "A";
break;
case 300<=$difference && $difference<600:
return "B";
break;
}
I think that switch must return A but it returs B. Whats wrong ???
I'm posting this merely as informative.
Switches can be used with expressions, however this is tricky to do:
<?php
$value = 300;
$other = 1;
switch (true) {
case $value <= 300 && $other:
$var = 'A';
break;
case $value >= 300 && !$other:
$var = 'B';
break;
case $value >= 300 && $other:
$var = 'C';
break;
case $value > 300 && $other:
$var = 'D';
break;
default:
$var = 'FALSE';
break;
}
echo $var;
The above code will display 'C' correctly. A combination of if/else statements is equivalent but I tend to find the switch more readable. Be sure to always include a default case whose value you can rely on (or maybe return from the function, throw an exception, etc).
You can also compare other variables, types, call functions (although not recommended), etc to match the value declared in the switch statement (in this case, true but can be an integer, string or any other base type).
Switches with expressions like you are using will not be evaluated as you might think. Use an if statement instead:
if(0<=$difference && $difference<300)
{
return "A";
}
else if(300<=$difference && $difference<600)
{
return "B";
}
In this case what is happening is $difference being equal to 0 is being interpreted as false. Thus you have switch(false). Each case is evaluated as a whole and there for case 2 actually returns false thus matching the switch statements evaluation and returning B. It also has to do with loose type checking. PHP.net

Build condition comparison for if statement

Is this possible?
$var_1 = 1;
$var_2 = 10;
$comparison = '>';
if($var_1 $comparison $var_2) {
// do something...
}
The syntax right now is not valid but is there a way to do this?
Not natively (except of course with eval). You will need to evaluate the various expressions yourself. Build a wrapper function and use a switch statement. Or for non-expression comparisons a simple map:
$var_1 = 1;
$var_2 = 10;
$comparison = '>';
$map = array(
">" => $var_1 > $var_2,
"<" => $var_1 < $var_2,
"==" => $var_1 == $var_2,
"!=" => $var_1 != $var_2,
);
if($map[$comparison]) {
// do something...
}
It is possible with
if (eval("{$var_1} {$comparison} {$var_2}")) {
But eval is strongly discouraged, so do this only if you can't achieve desired result otherwise
EDIT
As #mario noted, until PHP 5.3 this doesn't work. In 5.3 it does. So for older versions it should be
if (eval("return {$var_1} {$comparison} {$var_2};")) {
You probably should use eval(). As like in other programming languages, PHP’s eval() is also powerful and dangerous — be careful.
If you write something like the following code:
if (eval("$var_1 $comparison $var_2")) {
// ...
}
It won’t work. Because PHP’s eval() doesn’t evaluate an expression, but just execute a statement. So you should do like:
eval("\$condition = $var_1 $comparison $var_2;"); // semicolon required!
if ($condition) {
// ...
}
It would work well except $var_1 or $var_2 is not number. For example, if $var_1 is a string like 'hello', the code eval() executes becomes:
eval("\$condition = hello > 2;");
To avoid breaking this code, you should escape dollar signs of $var_1 and $var_2:
eval("\$condition = \$var_1 $comparison \$var_2;"); // don't escape $comparison's.
I'm not sure if this is possible without the hackish use of an eval statement. You could of course wrap simply test what comparison is being used within another if statement.
if($comparison == '>' && $var_1 > $var_2)
//Do something
elseif($comparison == '<' && $var_1 < $var_2)
//Do something, and so on
The eval method should work too if you build you code into an a string.
if(eval("$var_1 $comparison $var_2")) //Do something
But the first method is probably far more preferable.
You could also create a few functions like isGreaterThan($arg1, $arg2), isLessThan($arg1, $arg2), and then store the name of the function you want in the variable $comparison. Then you would use call_user_func_array() when you want to use it. Like so :
function isGreaterThan($val1, $val2) {
return $val1 > $val2;
}
/////////////
$var_1 = 1;
$var_2 = 10;
$comparison = "isGreaterThan";
if(call_user_func_array($comparison, array($var_1, var_2))) {
//do something
}
Sounds like you've got a few options. Hope this helps.
make the string a conditional, returning a value if true or false
short form if statement
$var_1 = 1;
$var_2 = 10;
$comparison = '>=';
eval("\$b=$var_1 $comparison $var_2?1:0;");
if ($b) {
//do something
}

Categories