i have a problem with my function which should combine logical operators according to data in array:
$arr = array(
0 => array(false, "or"),
1 => array(false, "or"),
2 => array(true)
);
the equation should be:
false or false or true
($arr[0][0] $arr[0][1] $arr[1][0] $arr[1][1] $arr[2][0])
And the result: true
But something wrong happens in function and it returns false.
What am i missing?
var_dump( arrayBoolValidation($arr) );
function arrayBoolValidation (array $arr) {
$num = count($arr);
$status = $arr[0][0];
for($i = 1; $i < $num; ++$i) {
if ($arr[$i-1][1] == "and") {
$status = filter_var($status, FILTER_VALIDATE_BOOLEAN) and filter_var($arr[$i][0], FILTER_VALIDATE_BOOLEAN);
} else if ($arr[$i-1][1] == "or") {
$status = filter_var($status, FILTER_VALIDATE_BOOLEAN) or filter_var($arr[$i][0], FILTER_VALIDATE_BOOLEAN);
}
}
return $status;
}
It's an operator precedence issue. and is not the same as &&. Look at http://php.net/manual/en/language.operators.precedence.php
= has higher priority than and, so $a = $b and $c; equals to $a = $b;.
You must use extra brackets ($a = ($b and $c);) or better use &&. Same thing about or (use ||).
Assuming that all conditions have to be evaluated:
Note: I have added the case when no operator is defined.
[...]
if (!isset($arr[$i-1][1])) {
$status = $status || $arr[$i][0]; // default: OR, && else
} else if ($arr[$i-1][1] == "and") {
$status = $status && $arr[$i][0];
} else if ($arr[$i-1][1] == "or") {
$status = $status || $arr[$i][0];
}
[...]
Change the following inside your loop:
if ($arr[$i-1][1] == "and") {
$status = (filter_var($status, FILTER_VALIDATE_BOOLEAN) and filter_var($arr[$i][0], FILTER_VALIDATE_BOOLEAN));
} else if ($arr[$i-1][1] == "or") {
$status = (filter_var($status, FILTER_VALIDATE_BOOLEAN) or filter_var($arr[$i][0], FILTER_VALIDATE_BOOLEAN));
}
You'll see the extra brackets.
If you don't put them, you set $status to filter_var($status, FILTER_VALIDATE_BOOLEAN), which will always be the same as the first entry (false in this case).
I think there is something wrong in loop
try,
for($i = 1; $i <=$num; ++$i) {
Related
I want to check different conditions into if statement based on different scenario (Will get the $status value as 'Y' or 'N'). Please check the code below and let me know the issue here.
$fstrto = "10";
$cstrto = "7";
if($status == 'N')
{
$cond = "$fstrto <= $cstrto";
}
else
{
$cond = "$fstrto >= $cstrto";
}
if($cond)
{
echo "Success";
}
This code is not working as it takes the "$fstrto <= $cstrto" as variable.
Remove the quotes. Use intval/doubleval if the input is a string as in $fstrto = intval($fstrto);.
$fstrto = 10;
$cstrto = 7;
if($status == 'N')
{
$cond = $fstrto <= $cstrto;
}
else
{
$cond = $fstrto >= $cstrto;
}
if($cond)
{
echo "Success";
}
Why it works: $cond is being assigned the value of a boolean expression, the values of which can be true or false. if($cond) just checks whether $cond is true or false
what is need to do is when using string as a php code use
eval — Evaluate a string as PHP code
Use below code work like charm:
$fstrto = "10";
$cstrto = "7";
if($status == 'N')
{
$cond = "$fstrto <= $cstrto";
}
else
{
$cond = "$fstrto >= $cstrto";
}
if(eval("return $cond;"))
{
echo "Success";
}
IMPORTANT:
Use of eval is highly discouraged
NEVER EVER use eval with params by POST/GET without sanitize them
When is eval evil in php?
You "$fstrto <= $cstrto" is a string now a compare statement.
$fstrto = "10";
$cstrto = "7";
if( ($status == 'N' && $fstrto <= $cstrto) || ($status != 'N' && $fstrto >= $cstrto) )
{
echo "Success";
}
Potentially turn it into a function that funnels into a switch statement like so:
function evaluateCondition($status, $a, $b) {
switch ($status) {
case 'Y':
return $a >= $b;
break;
case 'N':
return $a <= $b;
break;
default:
// Error Log. Unknown Status.
}
}
Any future addition can be appended onto the switch statement as necessary, if it gets more convoluted have each case return a separate function() to improve readability.
In terms of the current version you could use it like so:
$result = evaluateCondition('Y', 5, 6);
var_dump($result); // bool(false)
Hope that helps.
$fstrto = "10";
$cstrto = "7";
$cond = false;
if($status == 'N')
{
if($fstrto <= $cstrto){
$cond = true;
}
}
else
{
if($fstrto >= $cstrto){
$cond = false;
}
}
if($cond)
{
echo "Success";
}
Any ideas how to shorten if statment in an elegant way.
My if statement:
if(getfoo1() == getfoo2() && getfoo2() == 1)
{
}
EDIT:
I'm looking for something like:
if(getfoo1() == getfoo2() ==1)
{
}
But I suppose we can't do this.
$a = getfoo1();
$b = getfoo2(); // less operations, while it not produces duplicate calls
if($a == $b && $b == 1){
// do something
}
$variable = ((getfoo1() == getfoo2() && getfoo2() == 1) ? $value1 : $value2);
More elegant, combined:
$a = getfoo1();
$b = getfoo2();
$variable = (($a == $b && $b == 1) ? $value1 : $value2);
Since we don't know the possible return values from the functions, if you assume they are integers then you can say:
$a = getfoo1();
$b = getfoo2();
if (($a * $b) === 1) { // strict equality for the win
echo 'hi';
}
The result would only be true iff both $a AND $b are 1.
Another way:
$both = array(getfoo1(), getfoo2());
// use array_diff_assoc so it checks multiple occurrences of the same value
$diffCount = count(array_diff_assoc($both, array(1, 1)));
if ($diffCount === 0) {
echo 'hi';
}
Since anyway getfoo2() == 1 must be true, a better approach is to first check whether getfoo2() is equal to 1. If it false no matter about 2nd condition. But If you first check getfoo1() == getfoo2() and and then check getfoo2() == 1 you have to check 2 conditions all the times.
Therefore go for
$a = getfoo1();
$b = getfoo2();
if($b == 1 && $a == $b)
{
// logiv
}
else
{
}
Try this.
$a = getfoo1();
$b = getfoo2();
if( intval($a && $b) === 1) {
echo 'hi';
}
I want to do something like this:
if( $a = 'something' && $b = substr( $a, 2 ) )
{
//do something
}
I mean, on an if condition, evaluate two conditions, and the second one passing the first assigned $a as a parameter to the second condition function substr().
It is just an example, so I don't want answers to this functionality, just generic answers.
The above code throws 'Undefined' $a, since $a is not still assigned.
I could do the next:
if( $a = 'something')
{
if( $b = substr( $a, 2 ) )
//do something
}
}
but this will make my code bigger.
Is there any way to achieve something like the first example?
Edit:
I don't want to compare. Just assign and ensure that $a and $b are not null, false, ...
Your only problem is the wrong precedence of the && and = operators. This works just fine:
if (($a = 'something') && $b = substr($a, 2))
This way, $a is undefined:
if ($a = 'something' && $b = substr($a, 2))
But if you give the = operator priority:
if (($a = 'something') && $b = substr($a, 2))
It will be set.
Moreover, you can simply write:
if( $b = substr( $a = 'something', 2 ) )
This question intrigued me along with #moonwave99 answer, so I did some testing with his last answer.
if( $b = substr( $a = NULL, 2 ) ) { echo "PASS"; } else { echo "FAIL"; }
FAIL
if( $b = substr( $a = FALSE, 2 ) ) { echo "PASS"; } else { echo "FAIL"; }
FAIL
if( $b = substr( $a = 0, 2 ) ) { echo "PASS"; } else { echo "FAIL"; }
FAIL
if( $b = substr( $a = TRUE, 2 ) ) { echo "PASS"; } else { echo "FAIL"; }
FAIL
if( $b = substr( $a = 233, 2 ) ) { echo "PASS"; } else { echo "FAIL"; }
PASS
if( $b = substr( $a = "SOMETHING", 2 ) ) { echo "PASS"; } else { echo "FAIL"; }
PASS
The only way to get it to fail was to pass the Boolean TRUE. But if you are expecting string values, it should fail all Boolean values, zero and NULL and evaluate to true on ints, floats, and string values. (Haven't tested with array, but I suspect it would fail for any non-primitive types). Interesting question.
Use isset() for that.Also keep in mind use == or === for comparison operations since = is assignment operator
if( (isset($a) && $a == 'something') && (isset($b) && $b == substr( $a, 2 )) )
{
//do something
}
I'm wanting to set the condition of a do-while loop with a variable. Here's my code...
$ans_type = mt_rand(1, 2);
if ($ans_type == 1){
$condition = '$work_b != $c';
$symbol = '=';
$final_note = '1';
} else {
$condition = '$work_b == $c';
$symbol = '≠';
$final_note = '2';
}
do{
$a = mt_rand(-25, 25);
$b = mt_rand(-25, 25);
$c = mt_rand(-25, 25);
$d = mt_rand(-25, 25);
if($op_1 == '–'){
$work_b = $b * -1;
} else {
$work_b = $b;
}
if($op_2 == '–'){
$work_d = $d * -1;
} else {
$work_d = $d;
}
} while ($a == 0 || $b == 0 || $c == 0 || $d == 0 || $condition);
Note the $condition variable that I want to put in the while() part of the loop. This produces an infinite loop though.
So, is there a way to use variables as conditions in loops?
You can use variables as conditions, however the reason your code produces an infinite loop is because you are not changing $condition within your while loop. Therefore, if $condition evaluates to true once, it will keep evaluating to true (as it never changes in your code).
What you're trying to do can be better achieved by using normal variables:
if( blah ) {
$conditionstate = false;
} else {
$conditionstate = true;
}
...
} while( ... || ($work_b == $c) == $conditionstate );
If you have more varied conditions, maybe a restructure is in order. If there really is no way to restructure it, I'm hesitant to suggest it, because so many people misuse it to terrible consequences, but eval does what you're looking for and can be safe (if not fast) if used carefully. Needing to use it is usually a sign that your program has a bad structure though.
p.s. These types of random number generation problems are much better solved with code like this:
$a = mt_rand(-25, 24);
if( $a >= 0 ) {
++ $a;
}
// $a is -25 to 25, but never 0
$b = mt_rand(-25, 23);
if( $b >= min( $a, 0 ) ) {
++ $b;
}
if( $b >= max( $a, 0 ) ) {
++ $b;
}
// $b is -25 to 25, but never 0 or a
That can be made more elegant, but you get the idea. No need to loop at all, and guaranteed to halt.
$ans_type = mt_rand(1, 2);
if ($ans_type == 1){
$condition = ($work_b != $c);
$symbol = '=';
$final_note = '1';
} else {
$condition = ($work_b == $c);
$symbol = '≠';
$final_note = '2';
}
You are passing $condition as a string. Just save the $condition variable as a boolean.
if i have statement:
$a = 1;
$b = 2;
$c = 3;
if($a == 1 && $b == 2 && $c == 3)
{
echo 'correct';
}
else
{
echo 'what variable's weren't matched';
}
Is there any way of knowing what didn't watch instead of writing everything separately?
Cheers!
No. Your expression was turned into a boolean, so apart from checking the equality(s) again you cannot find out which triggered the "false".
You need to test each individually, but you could do something like this:
$a = 1;
$b = 2;
$c = 3;
$a_matched = $a == 1;
$b_matched = $b == 1;
$c_matched = $c == 1;
if($a_matched && $b_matched && $c_matched)
{
echo 'correct';
}
else
{
if (!$a_matched) echo 'a did not match!';
if (!$b_matched) echo 'b did not match!';
if (!$c_matched) echo 'c did not match!';
}
but that's less clear than just:
$a = 1;
$b = 2;
$c = 3;
if($a == 1 && $b == 2 && $c == 3)
{
echo 'correct';
}
else
{
if (!$a == 1) echo 'a did not match!';
if (!$b == 2) echo 'c did not match!';
if (!$c == 3) echo 'b did not match!';
}
Actually, heh, I take back my comment. You can rely on the boolean short-circuiting to set a variable indicating the last part of the conditional which was true:
if (($x = 'a') && $a == 1 && ($x = 'b') && $b == 2 && ($x = 'c') && $c == 3) {
echo "correct\n";
} else {
echo "$x is wrong\n";
}
Note, I would never write this in production code because it's goofy and very hard to understand what's supposed to be going on. But fun to fiddle with, at least.
Nope! That's not possible. You can make life a lot simpler by using arrays, though:
$results = array(1, 2, 4);
$expected = array(1, 2, 3);
$count = count($results);
$wrong = array();
for($i = 0; $i < $count; $i++) {
if($results[$i] !== $expected[$i]) {
$wrong[] = $i;
}
}
if(count($wrong) > 0) {
echo "There were wrong ones. They were at positions: " . implode(', ', $wrong);
} else {
echo "All good!";
}
For example.