PHP IF statement for Boolean values: $var === true vs $var - php

I know this question is not really important.. however I've been wondering:
Which of the following IF statements is the best and fastest to use?
<?php
$variable = true;
if($variable === true)
{
//Something
}
if($variable)
{
// Something
}
?>
I know === is to match exactly the boolean value. However is there really any improvement?

Using if ($var === true) or if ($var) is not a question of style but a question of correctness. Because if ($var) is the same as if ($var == true). And == comparison doesn’t check the type. So 1 == true is true but 1 === true is false.

As far as speed, I agree with Niels, it's probably negligible.
As far as which if statement is best to test with, the answer probably depends on the expected casting and values $variable can have.
If $variable is using 0 and 1 as a true/false flag then if ( $variable ) or if ( !$variable ) would work, but if it's an integer result as in strpos() you'll run into problems ... if possible, I'd recommend using an actual boolean value rather than 0 / 1.
... maybe this will help clarify; comment out the variations of $var to see the various results.
<?php
$var = true;
$var = 1;
$var = false;
$var = 0;
if ( $var ) {
echo 'var = true <br />';
}
if ( $var === true ) {
echo 'var is a boolean and = true';
}
if ( !$var ) {
echo 'var = false <br />';
}
if ( $var === false ) {
echo 'var is a boolean and = false';
}

Just a fact:
time php -r '$r = true; for($i = 0; $i < 10000000; $i++) { if($r == true) {} }'
time php -r '$r = true; for($i = 0; $i < 10000000; $i++) { if($r) {} }'
The second one is faster than the first.

=== is really helpful in strstr/stristr when the first needle is in position 0 in the haystack. If you don't use === or !== you could have a bug on your hands.
$str = "four score and...";
$position = strstr($str,'four');
if($position===FALSE) return FALSE;

I'm not really deep into the technical stuff of PHP, but in the first case
if($variable === true)
$variable has to have the exact same type as true for the if statement to be true. In other words, $variable has not only to resolve to true, but also has to be a boolean. So that's 2 operations, value-checking and type-checking.
In the second case
if($variable)
$variable only has to resolve to true. So only value checking occurs. I infer that that takes the computer a little less time.
Practically speaking: the differences in speed are probably negligible.

Related

PHP check if a variable is empty or not

In my case, the variables $nr and $str can have only two possible values. $nr can contain integer/numeric or null, not "null" between double quotes. $str can contain a string value or null. Can I just check if the variables are empty or not like this?
if ($nr) {}
if (! $nr) { return; }
if ($str) {}
if (! $str) { return; }
I think the answer is Yes but some code snippets of others made me doubt about that because they check it as following.
if (empty($var) || "" === $var || null === $var) { return; }}
I think this is unnecessary. To be specific, it is in PHP7.4.
You can check https://www.php.net/manual/en/types.comparisons.php to see what can be used to check if something is truthy or falsy. Below is the table of the link before condensed into a table of things you can plug into an if statement and what the results will be.
Before utilizing these tables, it's important to understand types and their meanings. For example, "42" is a string while 42 is an int. false is a bool while "false" is a string.
Expression
bool : if($x)
$x = "";
false
$x = null;
false
var $x;
false
$x is undefined
false
$x = array();
false
$x = array('a', 'b');
true
$x = false;
false
$x = true;
true
$x = 1;
true
$x = 42;
true
$x = 0;
false
$x = -1;
true
$x = "1";
true
$x = "0";
false
$x = "-1";
true
$x = "php";
true
$x = "true";
true
$x = "false";
true
if ($var)/if (!$var) simply check for truthy/falsey values respectively (they're complimentary opposites, which one you choose is merely a question of which makes more sense in your flow). Falsey values in PHP are:
false
null
0, -0, 0.0, -0.0
"0" (0 as a string)
"" (empty string)
array() (empty array)
empty SimpleXML objects (interesting special case; thanks Obama! 🤔)
Everything else is truthy.
So, if none of your desired values fall into this list and all of your undesired values are in this list, then a simple if ($var)/if (!$var) will do just fine. If your desired/undesired list does not happen to align with this and you want some of column A but also some of column B, then you need to do more specific and complicated checks.
The only time you'll want to use emtpy is if the variable you're checking may legitimately not exist. empty($var) is just !$var, but doesn't raise an error if $var doesn't exist at all. That's its only purpose, and you do not want to suppress error reporting unless you have to. In a properly written program where you declare your variables properly, there should be very very little use for empty, since you should know what variables exist and which don't.

Why does this PHP assignment in a loop always print the first value?

I'm very confused as to the output of this small piece of test code:
<?php
$count = 0;
while ($fn_retval = do_the_thing($count) !== false) {
print $fn_retval."\n";
$count++;
}
function do_the_thing($count) {
if ($count > 3) {
return false;
} else {
return $count;
}
}
?>
The output is:
$ php ./test.php
1
1
1
1
So it is correctly performing 4 iterations but always printing the return value of the first iteration. I feel like I must have missed something really obvious because this makes no sense.
Can somebody explain what's going on here because it seems like I can't use that assign-and-check construct in the way I thought I could.
The problem is that the order in which
$fn_retval = do_the_thing($count) !== false
is evaluated. If you check the Operator Precedence, you will see that !== is a higher precedence than =, so it's evaluated as
do_the_thing($count) !== false
and the result is then assigned to $fn_retval.
To force the order you are after, use brackets to explicitly do the assignment first...
while (($fn_retval = do_the_thing($count)) !== false) {

Boolean assignment operators in PHP

I find myself doing this kind of thing somewhat often:
$foo = true;
$foo = $foo && false; // bool(false)
With bitwise operators, you can use the &= and |= shorthand:
$foo = 1;
$foo &= 0; // int(0)
Given that bitwise operations on 1 and 0 are functionally equivalent to boolean operations on true and false, we can rely on type-casting and do something like this:
$foo = true;
$foo &= false; // int(0)
$foo = (bool)$foo; // bool(false)
...but that's pretty ugly and defeats the purpose of using a shorthand assignment syntax, since we have to use another statement to get the type back to boolean.
What I'd really like to do is something like this:
$foo = true;
$foo &&= false; // bool(false)
...but &&= and ||= are not valid operators, obviously. So, my question is - is there some other sugary syntax or maybe an obscure core function that might serve as a stand-in? With variables as short as $foo, it's not a big deal to just use $foo = $foo && false syntax, but array elements with multiple dimensions, and/or object method calls can make the syntax quite lengthy.
In a way you have answered your own question:
bitwise operations on 1 and 0 are functionally equivalent to boolean operations on true and false
Bearing in mind that PHP is a weakly typed language, so it is not necessary to typecast to and from strict boolean values as 1 and 0 are equivalent to true and false (except strict equality, see below).
Consider the following code, using your examples:
$foo = true;
$foo &= false;
if (!$foo) {
echo 'Bitwise works!';
}
$bar = true;
$bar = $bar && false;
if (!$bar) {
echo 'Boolean works!';
}
// Output: Bitwise works!Boolean works!
Given PHP's implicit type juggling, falsy values, and with the exception of strict equaltiy, I'm hard pressed to see where such shorthand operations of &&= and ||= would not yield the same result as &= and |=. Especially when evaluating boolean values. It's likely why such shorthands don't exist in PHP.
Update
Some quick benchmarks prove these are indeed equivalent, except for truthy arrays/objects:
<?php
$values = array(false, 0, 0.0, "", "0", array(), 12, "string", array(1));
foreach ($values as $value) {
$bit_test = true;
$bit_test &= $value;
$bool_test = true;
$bool_test = $bool_test && false;
if ($bit_test != $bool_test) {
echo 'Difference for: ';
var_dump($value);
}
}
// Output:
// Difference for: array(1) {
// [0]=>
// int(1)
// }
As Jason mentioned, bitwise operators will work and it will not be necessary to convert the result back to boolean, as PHP will already handle their value as a boolean properly.
If you want an alternative that does not use bitwise operators, for the sake of readability or if you want strict equality, you can use this method :
function OrOp(&$booleanVar, $conditions)
{
$booleanVar = $booleanVar && $conditions;
return $booleanVar;
}
Which means, you could change this :
$foo = $foo && false;
To this :
OrOp($foo, false);
It would also work with multiple conditions :
OrOp($foo, $condition1 && $condition2 && $condition3);
Right, &&= and ||= operators are indeed missing in PHP because bitwise operators can not be used as a replacement (without casting).
Here is an example you would expect to return true but returns false:
$a = true;
$a &= 10; // => returns 0 (false) because 1 & 10 = 0
The missing &&= operator would return true because 1 && 10 = true
$a = true;
$a &&= 10; // => $a would be true

PHP - Unexpected behaviour using == (equal) and === (identical)

I had the following in my code:
$mixed = array();
$mixed[0] = "It's a zero!";
$mixed['word'] = "It's a word!";
foreach ($mixed as $key => $value) {
if ($key == 'word') {
echo $value.'<br />';
}
}
The above would for some reason print both "It's a zero!" and "It's a word!". I was expecting it to print only "It's a word!". Why is that?? I feel like I am missing something important. When I was using === in the if statement, it worked as expected, in other words it printed only "It's a word!". I know there's a difference between the equal and identical operators, but the first example is not equal is it?
== does the type-conversion for you before comparison.
When you did an == with an integer 0, it converted 'word' into the appropriate integer value.
intval() returns 0 when supplied a pure-string, so 0 matched. The other was matched in string-context, and that matched as well.
=== does no such implicit conversion, so it returned true only in one case, when the strings were actually identical.
PHP variables have type.
== checkes equality after conversion to the same type, === also checks the type. Use var_dump to see what the real types are.
See #Cthulhu 's answer above which is much clear.
Apart from that, here is a different example.
strpos() function returns the position of the needle from haystack.
<?php
$pos_a = strpos('apple', 'a'); // a is in the first position.
$pos_b = strpos('apple', 'b'); // there is no b.
if ($pos_a){
echo 'we got a!'."\n";
}
if ($pos_b){
echo 'we got b!'."\n";
}
strpos return FALSE if the needle is not found. But you will see that php does not run any echo statement.
If you var_dumo()'d these 2 values, you will see that $pos_a and $pos_b contain 0 and FALSE.
if statement just failed because 0 and FALSE both are considered FALSE unless you use ===
Now try this:
<?php
$pos_a = strpos('apple', 'a'); // a is in the first position.
$pos_b = strpos('apple', 'b'); // there is no b.
if ($pos_a !== FALSE){
echo 'we got a!'."\n";
}
if ($pos_b !== FALSE){
echo 'we got b!'."\n";
}
Now you will see the desired result as it echos "we got a!".
$a == $b Equal TRUE if $a is equal to $b after type juggling.
$a === $b Identical TRUE if $a is equal to $b, and they are of the same type.
it looks that
if you check 0 against a string with == then PHP returns true:
php -r 'var_dump(0 == "statuses");'
-> returns TRUE
but not if your string has a number at the beginning:
php -r 'var_dump(0 == "2statuses");'
-> returns FALSE
from the specs I get it that it attempts a conversion - in this case the string to number.
so better use ===
http://php.net/manual/en/language.operators.comparison.php

Does PHP have short-circuit evaluation?

Given the following code:
if (is_valid($string) && up_to_length($string) && file_exists($file))
{
......
}
If is_valid($string) returns false, does the php interpreter still check later conditions, like up_to_length($string)?
If so, then why does it do extra work when it doesn't have to?
Yes, the PHP interpreter is "lazy", meaning it will do the minimum number of comparisons possible to evaluate conditions.
If you want to verify that, try this:
function saySomething()
{
echo 'hi!';
return true;
}
if (false && saySomething())
{
echo 'statement evaluated to true';
}
Yes, it does. Here's a little trick that relies on short-circuit evaluation. Sometimes you might have a small if statement that you'd prefer to write as a ternary, e.g.:
if ($confirmed) {
$answer = 'Yes';
} else {
$answer = 'No';
}
Can be re-written as:
$answer = $confirmed ? 'Yes' : 'No';
But then what if the yes block also required some function to be run?
if ($confirmed) {
do_something();
$answer = 'Yes';
} else {
$answer = 'No';
}
Well, rewriting as ternary is still possible, because of short-circuit evaluation:
$answer = $confirmed && (do_something() || true) ? 'Yes' : 'No';
In this case the expression (do_something() || true) does nothing to alter the overall outcome of the ternary, but ensures that the ternary condition stays true, ignoring the return value of do_something().
Bitwise operators are & and |.
They always evaluate both operands.
Logical operators are AND, OR, &&, and ||.
All four operators only evaluate the right side if they need to.
AND and OR have lower precedence than && and ||. See example below.
From the PHP manual:
// 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 before the "or" operation occurs
// Acts like: (($f = false) or true)
$f = false or true;
In this example, e will be true and f will be false.
Based on my research now, PHP doesn't seem to have the same && short circuit operator as JavaScript.
I ran this test:
$one = true;
$two = 'Cabbage';
$test = $one && $two;
echo $test;
and PHP 7.0.8 returned 1, not Cabbage.
No, it doesn't anymore check the other conditions if the first condition isn't satisfied.
I've create my own short-circuit evaluation logic, unfortunately it's nothing like javascripts quick syntax, but perhaps this is a solution you might find useful:
$short_circuit_isset = function($var, $default_value = NULL) {
return (isset($var)) ? : $default_value;
};
$return_title = $short_circuit_isset( $_GET['returntitle'], 'God');
// Should return type 'String' value 'God', if get param is not set
I can not recall where I got the following logic from, but if you do the following;
(isset($var)) ? : $default_value;
You can skip having to write the true condition variable again, after the question mark, e.g:
(isset($super_long_var_name)) ? $super_long_var_name : $default_value;
As very important observation, when using the Ternary Operator this way, you'll notice that if a comparison is made it will just pass the value of that comparison, since there isn't just a single variable. E.g:
$num = 1;
$num2 = 2;
var_dump( ($num < $num2) ? : 'oh snap' );
// outputs bool 'true'
My choice: do not trust Short Circuit evaluation in PHP...
function saySomething()
{
print ('hi!');
return true;
}
if (1 || saySomething())
{
print('statement evaluated to true');
}
The second part in the condition 1 || saySomething() is irrelevant, because this will always return true. Unfortunately saySomething() is evaluated & executed.
Maybe I'm misunderstood the exact logic of short-circuiting expressions, but this doesn't look like "it will do the minimum number of comparisons possible" to me.
Moreover, it's not only a performance concern, if you do assignments inside comparisons or if you do something that makes a difference, other than just comparing stuff, you could end with different results.
Anyway... be careful.
Side note: If you want to avoid the lazy check and run every part of the condition, in that case you need to use the logical AND like this:
if (condition1 & condition2) {
echo "both true";
}
else {
echo "one or both false";
}
This is useful when you need for example call two functions even if the first one returned false.

Categories