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.
Related
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;
I have 5 variables $a $b $c $d $e . These variables has numerical values. Im trying to compare these variables where each variable will be compared to the rest and if the condition is true it echoes something. Here is my code
if ($a > ($b && $c && $d && $e)) {
$result = '<div>Im A</div>'
} else if ($b > ($a && $c && $d && $e)) {
$result = '<div>Im B</div>'
} else if ($c > ($a && $b && $d && $e)) {
$result = '<div>Im C</div>'
} else if ($d > ($a && $b && $c && $e)) {
$result = '<div>Im D</div>'
} else if ($e > ($a && $b && $c && $d)) {
$result = '<div>Im E</div>'
}
return $result;
The result stops at first condition even though it is false and it should pass it to other conditions.
Some different approach:
$a = 1;
$b = 3;
$c = 4;
$d = 5;
$e = 0;
// Make array [a=>1, b=>3...]
$arr = compact('a','b','c','d','e');
// Sort it in descending order with saving keys
arsort($arr);
// Get the 1st key
echo 'I\'m ' . strtoupper(key($arr)); // I'm D
First of all - you have parentheses around ($b && $c && $d && $e), this means that in $a > ($b && $c && $d && $e) the result of ($b && $c && $d && $e) will be counted first, and then will be compared to $a.
So, $a > ($b && $c && $d && $e) is not
$a is greater than $b and $a is greater than $c and etc.
it is
$a is greater than result of ($b and $c and $d and $e)
And result of $b and $c and $d and $e is either true or false.
So, in the end you compare $a > true or $a > false. According to value of $a you can get different results.
In a simple case, if you want to check if something is greater than anything else you need to write a condition like:
if ($a > $b && $a > $c && $a > $d && $a > $e) {
Other more tricky solutions you will find in other users' anwers.
You can iterate your five variables and keep track of the one with the highest value.
for ($i='a', $x = 0, $max = 'x'; $i <= 'e'; $i++) {
if ($$i > $$max) {
$max = $i;
}
}
$result = "<div>I'm " . strtoupper($max) . "</div>";
I think you should steer clear of if statements ;) Here's a solution without them that can be used with any number of variables. You could use the $key as an index into a list of functions and make the program extensible.
// Make the numbers into an array
$o = [$a, $b, $c, $d, $e];
// Find the highest value
$max = max($o);
// Look up the highest value to get the index
$key = array_search($max, $o);
// Now you know which one it is, you can do anything with it!
switch ($key) {
case 0: $result = '<div>Im A</div>'; break;
case 1: $result = '<div>Im B</div>'; break;
...
}
Try this:
$array = ['A'=>$a,'B'=>$b,' C'=>$c,'D'=>$d,'E'=> $e];
$maxs = array_keys($array, max($array));
foreach ($maxs as $maxi )
echo '<div>Im '.$maxi.'</div>."<br>"';
This way it covers cases were there are multiple max values.
Refer to this answer for more about how it works.
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.
I want to write a test case to make sure a function call sets an array; however, I don't find a way to compare two arrays to make sure two empty arrays are not equal.
// code to be tested (simplified)
$foo = null;
function setFoo($input) {
global $foo;
$foo = array(); // BUG!!! The correct line would be: $foo = $input;
}
// test code
// given
$input = array();
// when
setFoo($input);
// then
if ($foo !== $input) {
// this block is not executed because "array() === array()" => true
throw new Exception('you have a bug');
}
So: What is the proper way to compare two PHP arrays and make sure, they are different instances (no matter if the content is the same)?
Memory locations refers to pointers. Pointers are not available in PHP. References are not pointers.
Anyway, if you want to check if $b is in fact a reference of $a, this is the closest you can get to an actual answer:
function is_ref_to(&$a, &$b) {
if (is_object($a) && is_object($b)) {
return ($a === $b);
}
$temp_a = $a;
$temp_b = $b;
$key = uniqid('is_ref_to', true);
$b = $key;
if ($a === $key) $return = true;
else $return = false;
$a = $temp_a;
$b = $temp_b;
return $return;
}
$a = array('foo');
$b = array('foo');
$c = &$a;
$d = $a;
var_dump(is_ref_to($a, $b)); // false
var_dump(is_ref_to($b, $c)); // false
var_dump(is_ref_to($a, $c)); // true
var_dump(is_ref_to($a, $d)); // false
var_dump($a); // is still array('foo')
I hope this solves your problem.
try this function . Arrays are compared like this with standard comparison operators
function standard_array_compare($op1, $op2)
{
if (count($op1) < count($op2)) {
return -1; // $op1 < $op2
} elseif (count($op1) > count($op2)) {
return 1; // $op1 > $op2
}
foreach ($op1 as $key => $val) {
if (!array_key_exists($key, $op2)) {
return null; // uncomparable
} elseif ($val < $op2[$key]) {
return -1;
} elseif ($val > $op2[$key]) {
return 1;
}
}
return 0; // $op1 == $op2
}
I really enjoy || operator in JavaScript, where we can do inline conditional assignation.
var a = 0;
var b = 42;
var test = a || b || 'default value';
console.log(test); // 42
This is clear to read, and don't take too many lines.
In PHP, this logical operator return booleans:
$a = 0;
$b = 42;
$test = $a || $b || 'default value';
print_r($test); // bool(true)
Of course, we can do inline assignation using ternaries:
$test = $a ? $a : $b ? $b : 'default';
print_r($test); // int(42)
But this make code ambiguous, this is not that easy to read.
So here my question come:
Do you know a nice PHP hack to do inline conditional assignation ?
In PHP 5.3+ you can do this:
$test = $a ?: ($b ?: 'default value');
This will work as long as you don't need to short-circuit side effects:
function either_or() {
$nargs = func_num_args();
if ($nargs == 0) {
return false;
}
$args = func_get_args();
for ($i = 0; $i < $nargs-1; $i++) {
if ($args[$i]) {
return $args[$i];
}
}
return $args[$nargs-1];
}
$test = either_or($a, $b, "Default value");