From what I see operator precedence makes sense in these two examples:
$a = false;
$b = true;
$c = $a || $b;
Here $c is true
$a = false;
$b = true;
$c = $a or $b;
Here $c is false
I understand the reasoning behind it. However the following:
$a = false;
$b = true;
return $a or $b;
Returns true, which puzzles me.
What is the reason for this?
or has lower precedence than =, so this:
$c = $a or $b;
Becomes this:
($c = $a) or $b;
But this doesn't make sense:
(return $a) or $b;
So you get this:
return ($a or $b);
Within an expression, operator precedence applies. =, || and or are all operators and $c = $a or $b is an expression. And according to operator precedence it evaluates as ($c = $a) or $b.
However, return is a statement. return is not an operator and does not group by operator precedence. It always evaluates as return <expression>, and therefore always as return ($a or $b).
The result of the expression $c = $a or $b is true BTW. $c is being assigned false in the course of the expression, but the expression overall returns the value true ($b). So even this would return true:
return $c = $a or $b;
Related
Is it possible to use the result of an if with an OR statement as a variable for a function?
As example:
$a = true;
$b = false;
if ($a || $b) {
$this->functionCall($a)
}
Other example:
$a = false;
$b = true;
if ($a || $b) {
$this->functionCall($b)
}
Third and final exmaple:
$a = true;
$b = true;
if ($a || $b) {
$this->functionCall($a, $b)
}
So I need to detect what variable is true and pass it as a paramater. Is this even possible?
Any helps is appreciated!
Many thanks in advance
I'd do the logic bit inside a two-parameter function if I were you, as such :
function myFunc($a = false, $b = false) {
if ($a == true)
echo 'a';
if ($b == true)
echo 'b';
}
myFunc(); // echoes nothing
$a = true;
$b = false;
myFunc($a, $b); // echoes 'a'
$a = false;
$b = true;
myFunc($a, $b); // echoes 'b'
$a = true;
$b = true;
myFunc($a, $b); // echoes 'ab'
PHP 5.6+ version, filter out the falsely values (you can pass a callback to array_filter for different checks) and use those with the splat operator.
$params = array_filter([$a, $b]);
$this->callFunction(...$params);
No need for any IF checks and confusing in IF assignments.
Explore Variadic functions and Argument unpacking.
where:
$b = true;
$c = 0;
$a = ($a ? ($a ? $b : $c) : ($c ? $a : $b));
I'm not sure how to work out a.
So I understand that this is a shorthand operator, and usually it's a case of:
$value ? true : false
meaning
if $a = true { true } else { false };
so:
if $a{
if $a{
true;}
else{
0;};
else{
if $0{
$a;}
else{
true;}
};
does this make the value of $a true?
The value of $a would be true
$b = true;
$c = 0;
$a = ($a ? ($a ? $b : $c) : ($c ? $a : $b));
The shorthand can be interpreted like this:
if($a) {
if($a) {
$a = $b;
} else {
$a = $c;
}
} else {
if($c) {
$a = $a;
} else {
$a = $b;
}
}
Because $a is false for not existing in the first place, it immediately jumps to the else statement in that. So the only part that matters to you is:
if($c) {
$a = $a;
} else {
$a = $b;
}
0 is the same as false, so $c will come back as false, therefore $a is equal to $b, which is true.
Edit:
There is some discussion on the notice that is thrown, but this fails to account for the fact that notices are not truly errors and because of this there is no interruption to the code. The result is not Notice: Undefined variable: a, the "result" (think these people mean output) would be blank if it weren't for us determining the value of $a at the end with var_dump. The question was as to what the value of $a becomes, not what appears on your screen.
Something displaying on your screen in re to a variable not being set has nothing to do with the value of what $a is.
If you execute the following code, the notice is not the only thing realized:
$b = true;
$c = 0;
$a = ($a ? ($a ? $b : $c) : ($c ? $a : $b));
var_dump($a);
So the output is:
E_NOTICE : type 8 -- Undefined variable: a -- at line 5
bool(true)
The fact that a notice was thrown does not prevent $a from becoming true.
Also notices are easily suppressed...
error_reporting(0);
$b = true;
$c = 0;
$a = ($a ? ($a ? $b : $c) : ($c ? $a : $b));
var_dump($a);
would result in $a still becoming true, and without seeing the notice.
bool(true)
If you run the code as is, you would get: Notice: Undefined variable: a in myfile.php on line 4
Therefore, I would postulate $a is set somewhere earlier. Yet, whatever value $a has prior, if $a is can be evaluated to true or false, $a would still be true after running your code for the following reason:
If $a were true, then the first part would yield $a = $b and we know $b = true.
if(TRUE) {
if(TRUE) {
$a = $b; //AND $b == TRUE
} else {
$a = $c;
}
} else {
...
}
If $a were false, then the second part would yield $a = $b again
if(FALSE) {
...
} else {
if(0) { // 0 will equate to FALSE
...
} else {
// 0 is the same as FALSE so we end up again with $a = $b
$a = $b; //AND $b == TRUE
}
}
In fact, if you run this code, it will show you the value of $a is true both times:
<?php
$a = false;
$b = true;
$c = 0;
$a = ($a ? ($a ? $b : $c) : ($c ? $a : $b));
echo $a;
$a = true;
$b = true;
$c = 0;
$a = ($a ? ($a ? $b : $c) : ($c ? $a : $b));
echo $a;
Are those expressions identical? which is more efficient?
Expression 1:
$a = 'default'
if($b != "") $a = $b;
Expression 2:
$a = $b == "" ? "default" : $b;
Does $a hold the same result in both cases?
you can easily test small PHP snippets in your command line by running it interactively:
$ php -a
Here you can write your code:
$a = "test";
$b = $a;
$b = $b == "" ? "default" : $b;
var_dump($b);
$c = $a == "" ? "default" : $a;
var_dump($c);
It should be the same - but I would go for expression 2.
I would write it like this:
$this->a = ($r[0] == "") ? "default" : $r[0];
All depend on the situation in hand. Both are valid but for multiple scenarios this one is quicker and much more efficient
$a = $b == "" ? "default" : $b;
I tried this way without effect:
$a = false;
$b = false;
$c = 'sometext';
$result = $a or $b or $c or exit('error: all variables are false');
and $result should be set to $c, but this gives value of bool(false) instead.
What about:
$result = $a ?: $b ?: $c ?: exit('doh!');
($result = $a) || ($result = $b) || ($result = $c) || exit("no");
or if you want 0 and empty string etc. not count as false:
(($result = $a) !== false) || (($result = $b) !== false) || (($result = $c) !== false) || exit("no");
think about whether this is really readable. You could also use the old fashioned way:
if ($a !== false)
$result = $a;
elseif ($b !== false)
$result = $b;
elseif ($c !== false)
$result = $c;
else
exit("no");
Edit: Just in case you ever need something dynamic ;-).
foreach(array('a','b','c') as $key)
if (($result = $$key) !== false)
break;
if ($result === false)
exit("no");
There's a couple of things going on here:
Firstly, in PHP the result of a boolean operation is a boolean.
Secondly, and more subtly, the "english" boolean operators (or and and) have a low precedence - lower than the assignment operator, =.
Therefore in this expression $result will always get the actual value of $a (regardless of $a's value), since the assignment is applied before the boolean operator.
// This has the same effect:
$result = $a or $b or $c;
// As this:
$result = $a;
$a or $b or $c; // this has no effect
This is confusing, and almost certainly not what you want.
To get the boolean result of whether any of $a, $b, $c is truthy (ie true, or castable to true) you can either use parentheses to force the precedence, or use the "C-style" operators (|| and &&) which have a higher precedence:
// These all have the same effect:
$result = ($a or $b or $c);
$result = $a || $b || $c;
if ($a or $b or $c)
$result = true;
else
$result = false;
if ($a || $b || $c)
$result = true;
else
$result = false;
If you're unsure about operator precedence it's best to use parentheses - they also tend to help make code more readable, since the order of evaluation is made much more obvious.
It's also generally better to not rely on implicit type conversions (especially casting non-numeric strings), since it tends to make for unclear code.
edit:
To answer the actual question, another approach (though I don't really recommend it in this case, since you say you're only interested in the first non-false value) would be to use array_filter without a callback - that would return an array of all the values in the input array that are truthy, with keys preserved.
eg:
$a = false;
$b = false;
$c = 'sometext';
$result = array_filter(array($a, $b, $c));
var_dump($result);
Outputs:
array(1) {
[2]=>
string(8) "sometext"
}
Result of a boolean operator is boolean in php.
$a = false;
$b = false;
$c = 'sometext';
$result = null;
foreach(array('a', 'b', 'c') as $k)
{
if($$k !== false)
{
$result = $$k;
break;
}
}
Also, consider moving your variables into an array.
I am trying to figure out the difference between $a=&$b and $a=$b.
I know & make the variable to be a reference variable. But the following test gave me the same result. Can anyone explain the difference? Thanks.
$a=5;
$b=6;
$a=&$b;
echo $a; //6
$a=5;
$b=6;
$a=$b;
echo $a; //6
First of all: you'll hardly ever need references, avoid the confusion of using them if you can.
$a=5; //assign value to a
$b=&$a; //make $b a reference to $a
$b=6; //assigning a value to $b assigns the same value to $a (as they point to the same location
echo $a; //6
$a=5; //assign a value to a
$b=$a; //set $b to the value of $a
$b=6; //set $b to another value leaves $a at it's original value
echo $a; //5
It matters more in a function when you send it in as a parameter.
For example:
<?php
function changeVariableWithReference(&$var)
{
$var += 1;
}
function changeVariableWithoutReference($var)
{
$var += 1;
}
$a = 5;
$b = 5;
changeVariableWithReference($a);
changeVariableWithoutReference($b);
print $a . ' ' . $b;
?>
The difference between $a = $b and $a =& $b is that with the former assignment operator the value is copied while with the latter reference operator the variable $a refers to the same value as $b.
You don’t see any difference when reading the value but you see it when writing the value:
$var = 123;
$copyOfVar = $var;
$referenceToVar =& $var;
$copyOfVar = 456;
echo 'var='.$var.'; copyOfVar='.$copyOfVar;
// "var=123; copyOfVar=456"
$referenceToVar = 456;
echo 'var='.$var.'; referenceToVar='.$referenceToVar;
// "var=456; referenceToVar=456"
When you use the & in an assignment, you can think of the new variable being a 'short-cut' to the original. If you don't use the &, it will be a 'copy' of the original.
$a = 5;
$b =& $a; // this $b is like a shortcut to $a. Change $b and $a will change too
$a = 5;
$b = $a; // this time, $b will be 5 - but not a shortcut to $a. Change $b and $a will still be 5.
A reference can be easily explained by simple graph. When you use copy by value ($a = $b) then something like that happens:
$a = 1000;
# $a -----> 1000
$b = $a;
# $a -----> 1000
# $b -----> 1000
# (two "pieces of memory" has been used)
But when you create a new reference to $a named $b then something like that happens:
$a = 1000;
$b =& $a;
# $a --\
# --> 1000
# $b --/
# (one "piece of memory" has been used but two different names ($a, $b) point on it)
You will get the ans, if you follow the following code (i have add some lines)
$a=5;
$b=6;
$a=&$b;
echo $a; //6
$b = 8;
echo $a; //8
$a=5;
$b=6;
$a=$b;
echo $a; //6
$b = 20;
echo $a; //6
with & simple, variable $a points the variable $b
without &, $b just copy into $a