Boolean assignment operators in PHP - 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

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.

PHP: Comparison within Assignment Statement

In my never-ending quest to optimise my line usage, I've just got a quick question about what exactly can go into as assignment statement in PHP (and other languages too, but I'm working on a PHP project).
In my program I have a certain boolean variable, which is toggled by a few things summarised by an if statement. I thought, hang on, that if statement will evaluate to a boolean value, can I just use that logic in one line, as opposed to wrapping a separate assignment statement inside the if. Basically my question is will:
$myVar = ($a == $b);
be equivalent to
if ($a == $b) { $myVar = true; }
else { $myVar = false; }
As you can see, this saves me one whole line, so it will impact my project hugely. /sarcasm
What you are looking for is a terinary operation. Something simialar to
$var = ($a === $b ? true : false);
echo $var;
Depending on the evaluation result of $a === $b the value of $var is then set.
Short answer, $myVar = ($a == $b); is the same as if ($a == $b) { $myVar = true; } else { $myVar = false; }.
And if you want to be even shorter, you can even remove the (...) and have it barely $myVar = $a == $b;

Variable assignment into if statement for example

I'm a bit confused about operator precedence actually.
Here is an example that doesn't match with the php official website
function getValue($key) {
$array = ['un' => 1, 'six' => 6];
if (array_key_exists($key, $array)) {
return $array[$key];
}
return null;
}
var_dump(null === $t1=getValue('un'));
var_dump(null === $t2=getValue('blablablaaaaaa'));
// And now I switch
var_dump($t3=getValue('un') === null);
var_dump($t4=getValue('blablablaaaaaa') === null);
OUTPUT
bool(false)
bool(true)
// After the switch
bool(false)
bool(true)
This is not what I was expecting for the two first outputs, because the comparison is higher-precedence than assignment. So php should've tried to compare null === $t1, or $t1 has not been declared yet, so a warning or error or whatever should've been raised. Or that didn't happen. Do you notice that PHP sometimes treat assignment before comparison although comparison is higher-precedence and thus should always be performed before assignment?. Any explanations about this?
My second question is: should this be avoided by always splitting up this kind of expression?
UPDATE
N.B
var_dump($t1, $t2, $t3, $t4);
// OUTPUT
int(1)
NULL
// After the switch
bool(false)
bool(true)
=== is non-associative.
Non-associative operators are operators that have no defined behavior when used in sequence in an expression.
And in docs
= has a lower precedence than most other operators, PHP will still allow expressions similar to the following: if (!$a = foo()), in which case the return value of foo() is put into $a.
So it can be assumed PHP (in any of the expression) will first assign the return value of the function to the variable and then compare.

PHP OR surprising behavior [duplicate]

This question already has answers here:
The behaviour of the or operator in PHP
(4 answers)
Closed 8 years ago.
I have some surprising results using OR as a logical OR in php.
Considering the following code:
$a = false;
$b = false;
$c = true;
# Test 1, using OR and assigning to a variable
$value = $a OR $b OR $c;
var_dump( $value );
# return bool(false) but why?
# Test 2, using OR directly in var_dump
var_dump( $a OR $b OR $c );
# return bool(true) as expected
# Test 3, using || and assigning to a variable
$value = $a || $b || $c;
var_dump( $value );
# return bool(true) as expected
# Test 4, using || directly in var_dump
var_dump( $a || $b || $c );
# return bool(true) as expected
Why Test 1 and Test 2 give different results even though they do the same logical operation?
The || operator and OR operator do not behave the same. They cannot be used interchangably.
If you want || behaviour, then use it. Do not use OR unless you're in a situation where || would do the wrong thing.
As for your situation, these two lines of code will behave exactly the same:
$value = $a OR $b OR $c;
($value = $a) OR $b OR $c;
In other words, your code is basically just:
$value = $a;
If you used the || operator, then these two are identical as if you had braces like this:
$value = $a || $b || $c;
$value = ($a || $b || $c);
For more details: http://php.net/manual/en/language.operators.precedence.php
If you wrap test 1 in parenthesis, it will behave as expected:
$value = ($a OR $b OR $c);
When you run var_dump on test 2, you get the expected result because var_dump is wrapping the operation in parenthesis.
It is usually a good idea to wrap an operation in parenthesis like this, especially with variable assignment.
Also, the "OR" keyword and "||" do not behave the same way. See documentation here:
http://php.net/manual/en/language.operators.logical.php

Do PHP's logical operators work as JavaScript's?

One of the things I like the most of JavaScript is that the logical operators are very powerful:
&& can be used to safely extract the value of an object's field, and will return null if either the object or the field has not been initialized
// returns null if param, param.object or param.object.field
// have not been set
field = param && param.object && param.object.field;
|| can be used to set default values:
// set param to its default value
param = param || defaultValue;
Does PHP allow this use of the logical operators as well?
PHP returns true orfalse. But you can emulate JavaScript's r = a || b || c with:
$r = $a ?: $b ?: $c;
Regarding 'ands', something like:
$r = ($a && $a->foo) ? $a->foo->bar : null;
PHP logical operators do not return the value on any of their sides : they will always get you a boolean.
For instance, doing :
$result = $a && $b;
Will always make $result contain a boolean : true or false -- and never $a nor $b.
You can set up similar functionality using ternary operators.
Revised:
With respect to logical ANDing in PHP to achieve the same kind of result as JavaScript, you could use a variant of the traditional ternary, as follows:
<?php
// prelim
$object = new stdClass;
$object->field = 10;
$param = new stdClass;
$param->object = $object;
// ternary variant
$field = !($param && $param->object)?: $param->object->field;
echo $field,"\n";
// alternative to ANDing
$field = get_object_vars( $param->object )["field"] ?? null;
echo $field,"\n";
See live code
The "Elvis" operator "?:" only assigns the result to $field if the conditional expression is false. So, if $param exists as well as $param->object, then you have to use the NOT operator ("!") in order to get the desired result.
You may also accomplish the objective of getting the field data without ANDing by utilizing the null coalescing operator ("??") in PHP 7 in tandem with get_object_vars().

Categories