Boolean assignment operators in PHP
Asked Answered
O

3

23

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.

Oersted answered 9/7, 2013 at 16:5 Comment(6)
What is wrong with $foo = $foo && false;? Or is it just curiosity?Lardner
@DanyCaissy: I explained in the last paragraph. There's nothing wrong with it; it's just that that syntax is redundant, and can get very lengthy (e.g. $some['big']['long']['variable'] = $some['big']['long']['variable'] && $some['other']['boolean'];).Oersted
You may want to change your examples. Logically, these will always yield the same result = $foo &= false; and $foo &&= false; for $foo = true. So I'm failing to see the problem/goal.Philosophy
@JasonMcCreary: It depends on your definition of "same." As my examples point out, the former yields int(0) and the latter yields bool(false). So while 0 == false because of implicit type-casting, 0 !== false.Oersted
This is still relevent 7 years latter with PHP7/8 type enforcement checks. Very easy to accidentally convert from a bool to an int if you use short syntax.Villareal
Knowing $mailsSent = (Swift_Mailer)$mailer->send($message) is false, if mail not sent, I've been using $mailsSent &= $mailer->send($message2) consecutively. After a year of such usage it was the first time, that I had different number of recipients in first and second mail group. Today I found out two things. First if mails are successfully sent send() method returns the number of mails sent and not true. Second &= is a bitwise assignment operator, meaning 1 + 2 = 0. Should've read the docs more thoroughly. Solved it with (bool)$mailer->send($message).Somatotype
P
6

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)
// }
Philosophy answered 9/7, 2013 at 16:35 Comment(6)
You're correct, but I was actually looking for a solution that didn't change the type (hence why my 3rd example was explicitly type-casting back into a bool). I have control over both the operands, and they're guaranteed to be bools, so I'd much rather just use the longer syntax than potentially introduce errors into the code by returning "falsy" values instead of a strict bool like the interface has documented.Oersted
Fair. Even though PHP is a weakly typed, dynamic language, I support writing such explicit code. My answer is based on that fact that for boolean values (and most other simple types) bitwise operators are equivalent to boolean operators. But if you want to use such a shorthand, you have to give up strict equality checks (or compare to 0/1). In the end, I don't really see the point. Nonetheless, I wanted to provide an answer for future readers.Philosophy
Keep in mind, you could always cast it before returning the value. Probably good practice anyway.Philosophy
@JasonMcCreary No, boolean and bitwise operators are not equivalent, though their output is. The big difference is, that PHP does not even execute an expression for boolean operates if the outcome makes no difference. So $res = sql_query() OR die(); is not equivalent to $res = sql_query(); $res |= die();.Angeli
@Matmarbon, correct, in these comments I forgot a key qualifier - functionally equivalent.Philosophy
Unfortunately with strong type checking that is no longer true @JasonMcCreary. $result = true; $result &= somefun() will change the type for $result from a bool to an int. I still see a usecase for a boolean assignment operator in php. In fact, that is the reaseon why I came here.Trista
L
2

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);
Lardner answered 9/7, 2013 at 16:20 Comment(4)
While helpful, it seems the OP is looking for something native and aware they can write custom code.Philosophy
I don't think there is something native that would do it for them, this is why I put this here. I'll remove my answer if I am proven wrong. While I'm sure OP could have came up with this method by himself, future readers that are less experienced might find it useful.Lardner
Did someone thing to post this to the PHP dev team?Trista
I did: on githubTrista
E
1

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
Erickericka answered 15/4, 2022 at 1:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.