Why did a simple || work like an if sequence? - php

In my last project I had to specify a value, normally I use the following statement:
<?php
$true = 1;
$false = 0;
$hasAccess = $true ? 1 : 0;
print $hasAccess;
?>
but this works to:
<?php
$true = 1;
$false = 0;
$hasAccess = $true || $false;
print $hasAccess;
?>
Why?
Update: I know what a OR / || is and what I have to expect from it. But I haven't seen this possibility any time before.

Because 0 is automaticly casted to (bool)false, and anything else (bool)true.
So what you are basicly saying is:
$hasaccess = true OR false;
See also:
http://php.net/manual/en/language.types.boolean.php
http://php.net/manual/en/language.operators.logical.php

Because
$true ? 1 : 0;
evaluates to 1, since $true is true, and
$true || $false;
also evaluates to 1, for the same reason.

The OR will return true if either side of the expression true.
Since $true = 1 then the expression as a whole is true.
Basically you're saying "if $true is true, or $false is true then then $hasAccess is true"

An || which is an OR statement returns weather one of the statements evaluates to true.
Examples:
$bool = true || false;
// $bool = true
$bool = false || true;
// $bool = true
$bool = false || false;
// $bool = false
$bool = false || true || false;
// $bool = true
$bool = false || 1;
// $bool = true
$bool = false || 'test';
// $bool = true

Related

PHP - Check if more than one condition is true in a given number of conditions

Is there an elegant way to check if multiple, but not all, conditions are true out of any given number of conditions?
For example, I have three variables: $a, $b, and $c.
I want to check that any two of these are true. So the following would pass:
$a = true;
$b = false;
$c = true;
But this wouldn't:
$a = false;
$b = false;
$c = true;
Also, I may want to check if 4 out of 7 conditions were true, for example.
I realise I can check each combination, but this would get more difficult as the number of conditions increased. Looping through the conditions and keeping a tally is the best option I can think of, but I thought there may be a different way to do this.
Thanks!
Edit: Thanks for all the great answers, they're much appreciated.
Just to throw a spanner in to the works, what if the variables weren't explicit booleans?
E.g.
($a == 2)
($b != "cheese")
($c !== false)
($d instanceof SomeClass)
A "true" boolean in PHP casts to a 1 as an integer, and "false" casts to 0. Hence:
echo $a + $b +$c;
...will output 2 if two out of the three boolean variables $a, $b or $c are true. (Adding the values will implicitly convert them to integers.)
This will also work with functions like array_sum(), so for example:
echo array_sum([true == false, 'cheese' == 'cheese', 5 == 5, 'moon' == 'green cheese']);
...will output 2.
You could put your variables in an array, and use array_filter() and count() to check the number of true values:
$a = true;
$b = false;
$c = true;
if (count(array_filter(array($a, $b, $c))) == 2) {
echo "Success";
};
I'd go for a method like the following:
if (evaluate(a, b, c))
{
do stuff;
}
boolean evaluate(boolean a, boolean b, boolean c)
{
return a ? (b || c) : (b && c);
}
What it says is:
If a is True, then one of b or c must be true too to comply with 2/3
True criterion.
Else, both b and c must be true!
If you want to expand and customise the conditions and the number of variables I'd go for for a solution like the following:
$a = true;
$b = true;
$c = true;
$d = false;
$e = false;
$f = true;
$condition = 4/7;
$bools = array($a, $b, $c, $d, $e, $f);
$eval = count(array_filter($bools)) / sizeof($bools);
print_r($eval / $condition >= 1 ? true : false);
Simply we evaluate the true's and we make sure that the % of True is equals or is better than what we want to achieve. Likewise you could manipulate the final evaluation expression to achieve what you want.
This should also work, and would allow you fairly easily to adjust to the numbers.
$a = array('soap','soap');
$b = array('cake','sponge');
$c = array(true,true);
$d = array(5,5);
$e = false;
$f = array(true,true);
$g = array(false,true);
$pass = 4;
$ar = array($a,$b,$c,$d,$e,$f,$g);
var_dump(trueornot($ar,$pass));
function trueornot($number,$pass = 2){
$store = array();
foreach($number as $test){
if(is_array($test)){
if($test[0] === $test[1]){
$store[] = 1;
}
}else{
if(!empty($test)){
$store[] = 1;
}
}
if(count($store) >= $pass){
return TRUE;
}
}
return false;
}
U can use while loop :
$condition_n = "x number"; // number of required true conditions
$conditions = "x number"; // number of conditions
$loop = "1";
$condition = "0";
while($loop <= $conditions)
{
// check if condition is true
// if condition is true : $condition = $condition + 1;
// $loop = $loop + 1;
}
if($condition >= $condition_n)
{
// conditions is True
}
else
{
// conditions is false
}
I think it is a little easy and short writing when you use operator "&" , "|" like this:
$a = true;
$b = true;
$c = false;
$isTrue = $a&$b | $b&$c | $c&$a;
print_r( $isTrue );
Let check by your self :D

Logical operators equation in php

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) {

Logical Operators and Precedence

So I just did some random test and understand the fundamentals of Precedence and the || and or operators but I'm having trouble understanding why $f changes:
$f = 0 || 1;
if ($f === 1){
echo "TRUE - $f";
}else{
echo "FALSE - $f";
}
$f = 0 or 1;
if ($f === 0){
echo "TRUE - $f";
}else{
echo "FALSE - $f";
}
Thanks for some insight.
What you are doing is the same as :
if (($f = 0) or 1){
// $f is being assigned the value 0, and the condition evaluates 0 or 1,
// 1 being equivalent to true, the condition is always true.
echo "TRUE - $f";
}else{
echo "FALSE - $f";
}
and
if ($f = (0 || 1)){ // which gives $f = true which returns true
echo "TRUE - $f";
}else{
echo "FALSE - $f";
}
if you want to check if $f is equal to a value or another you would do
if ($f === 0 or $f === 1)
Be aware that in php, by default an int 1 will be evaluated to bool true unless you do a strict comparison === or !==
It's normal to evaluate always to True. The reason is that OR means if that one of the values is True it will take this one.
Update to your new question:
The answer is that "||" has a greater precedence than "or"
// The result of the expression (false || true) is assigned to $e
// Acts like: ($e = (false || true))
$e = false || true;
// The constant false is assigned to $f and then true is ignored
// Acts like: (($f = false) or true)
$f = false or true;
You can learn more at the PHP manual website here which I found this example
the problem is here: "if ($f = 0 or 1){" :
"=" means you give the variable $f the value 0
You should use :
"==" : checks if the values are equal
"===" : checks if the left variable is identical to the right variable (value, type, etc.)

AND operator behavior with/without brackets

$a = true and false; //true
$b = true && false; //false
$c = (true and false); //false
$d = (true && false); //false
Why gives case 'a' true?
I thought that and and && has the same precedence but they don't.
As stated in the documentation, this is expected bahvior
// The constant true is assigned to $h and then false is ignored
// Acts like: (($h = true) and false)
$h = true and false;
http://php.net/manual/en/language.operators.logical.php
The constant true is assigned to $a and then false is ignored. It's all about operator precedences

Weird PHP number issue

Here is the simple code:
$result = 0;
$result = $obj->delete($this_id);
echo "Result:" . $result;
var_dump($result);
if ( (int) $result < 0 || $result == null ) {
echo "Here" . $result;
var_dump($result);exit;
}
Here is the result:
Result:0int(0)
Here0int(0)
Its not supposed to enter into if block. Because $result is = 0. Not < 0.
Am I missing something or PHP handles this differently?
The comparison to null should be === instead of ==. Since null can evalulate to 0, the comparision evaluates (0 == null) = true
if ( (int) $result < 0 || $result === null ) {
See http://php.net/manual/en/language.operators.comparison.php for more information
It looks like the cast to an int type is making your variable test incorrectly against 0.
Replace if( (int) $result ... with if( $result ...
Its not the first validation which matches:
var_dump(0 == null); //true
var_dump(false == null); //true

Categories