Логические операторы присваивания в PHP

Я часто занимаюсь такими вещами:

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

С побитовыми операторами вы можете использовать сокращение &= и |=:

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

Учитывая, что побитовые операции над 1 и 0 функционально эквивалентны булевым операциям с true и false, мы можем полагаться на литье типов и делать что-то вроде этого:

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

... но это довольно уродливо и побеждает цель использования синтаксиса сокращенного присваивания, так как мы должны использовать другое утверждение, чтобы вернуть тип в boolean.

То, что я действительно хотел бы сделать, это примерно так:

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

... но &&= и ||=, очевидно, не являются действительными операторами. Итак, мой вопрос: есть ли какой-то другой сладкий синтаксис или, может быть, неясная основная функция, которая может служить в качестве stand-in? Поскольку переменные как короткие, чем $foo, не стоит просто использовать синтаксис $foo = $foo && false, но элементы массива с несколькими измерениями и/или вызовы метода объекта могут сделать синтаксис довольно продолжительным.

Ответы

Ответ 1

В каком-то смысле вы ответили на свой вопрос:

побитовые операции на 1 и 0 функционально эквивалентны булевым операциям с истинным и ложным

Принимая во внимание, что PHP является слабо типизированным языком, поэтому нет необходимости прибегать к строковым логическим значениям и от них, поскольку 1 и 0 эквивалентны true и false (кроме строгого равенства, см. Ниже).

Рассмотрим следующий код, используя ваши примеры:

$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, значения фальши и за исключением строгого равенства, мне трудно понять, где такие сокращенные операции &&= и ||= не будут давать тот же результат, что &= и |=. Особенно при оценке булевых значений. Вероятно, почему такие сокращения не существуют в 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

Как упоминал Джейсон, побитовые операторы будут работать, и нет необходимости преобразовать результат обратно в логическое, поскольку PHP уже будет обрабатывать их значение как логическое правильно.

Если вы хотите альтернативу, которая не использует побитовые операторы, для удобства чтения или если вы хотите строгого равенства, вы можете использовать этот метод:

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

Это означает, что вы можете изменить это:

$foo = $foo && false;

К этому:

OrOp($foo, false);

Он также будет работать с несколькими условиями:

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