PHP 中的布尔赋值运算符

2022-08-30 22:26:58

我发现自己经常做这种事情:

$foo = true;
$foo = $foo && false; // bool(false)

使用按位运算符,您可以使用 和 速记:&=|=

$foo = 1;
$foo &= 0; // int(0)

鉴于 对 和 的按位运算在 功能上等效于 和 上的布尔运算,我们可以依赖类型转换并执行如下操作:10truefalse

$foo = true;
$foo &= false; // int(0)
$foo = (bool)$foo; // bool(false)

...但这非常丑陋,并且违背了使用速记赋值语法的目的,因为我们必须使用另一个语句来使类型恢复为布尔值。

我真正想做的是这样的:

$foo = true;
$foo &&= false; // bool(false)

...但显然,它们不是有效的运算符。所以,我的问题是 - 是否有其他一些含糖语法,或者可能是一个晦涩的核心函数,可以作为替身?对于短至 的变量,仅使用语法并不是什么大问题,但是具有多个维度的数组元素和/或对象方法调用可能会使语法变得非常冗长。&&=||=$foo$foo = $foo && false


答案 1

在某种程度上,你已经回答了自己的问题:

对 1 和 0 的按位运算在功能上等效于对 true 和 false 的布尔运算

请记住,PHP 是一种弱类型语言,因此没有必要将严格布尔值与 和 等价于 和 (严格相等除外,见下文)进行类型转换。10truefalse

请考虑以下代码,使用您的示例:

$foo = true;
$foo &= false;

if (!$foo) {
  echo 'Bitwise works!';
}

$bar = true;
$bar = $bar && false;

if (!$bar) {
  echo 'Boolean works!';
}

// Output: Bitwise works!Boolean works!

鉴于 PHP 的隐式类型杂耍falsy 值,并且除了严格的均衡之外,我很难看出 and 的这种速记操作在哪些方面不会产生与 和 相同的结果。尤其是在计算布尔值时。这可能就是为什么PHP中不存在这样的速记的原因。&&=||=&=|=

更新

一些快速基准测试证明这些确实是等效的,除了真实数组/对象:

<?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)
// }

答案 2

正如Jason所提到的,按位运算符将起作用,并且没有必要将结果转换回布尔值,因为PHP已经将它们的值作为布尔值正确处理。

如果你想要一个不使用按位运算符的替代方法,为了可读性或者如果你想要严格的相等,你可以使用这种方法:

function OrOp(&$booleanVar, $conditions)
{
    $booleanVar = $booleanVar && $conditions;
    return $booleanVar;
}

这意味着,您可以更改此设置:

$foo = $foo && false;

对此:

OrOp($foo, false);

它也适用于多种条件:

OrOp($foo, $condition1 && $condition2 && $condition3);

推荐