Разбор строки в логическое значение в PHP

126

Сегодня я играл с PHP и обнаружил, что строковые значения «истина» и «ложь» неправильно преобразованы в логические значения в условии, например, учитывая следующую функцию:

function isBoolean($value) {
   if ($value) {
      return true;
   } else {
      return false;
   }
}

Если я выполню:

isBoolean("true") // Returns true
isBoolean("") // Returns false
isBoolean("false") // Returns true, instead of false
isBoolean("asd") // Returns true, instead of false

Это работает только со значениями «1» и «0»:

isBoolean("1") // Returns true
isBoolean("0") // Returns false

Есть ли в PHP встроенная функция для преобразования строк «истина» и «ложь» в логические значения?

отметка
источник
В вашем коде isBoolean("")должно возвращаться false.
BoltClock
Вам следует подумать об изменении принятого ответа на ответ Эрика Карона. Он показывает вам встроенную функцию, которая делает то, что вы просите.
Code Commander
1
PHP не думает о том, что говорит строка, «false» - это всего лишь пять символов, которые ничего не значат. Но это что- то, поэтому логическое значение оценивается, trueдаже если человеческому читателю оно показалось бы более интуитивным, чем оно означало FALSE.
zeel

Ответы:

414

Для этого существует собственный PHP-метод, который использует PHP-метод filter_var:

$bool = filter_var($value, FILTER_VALIDATE_BOOLEAN);

Согласно руководству PHP :

Возвращает ИСТИНА для «1», «истина», «вкл» и «да». В противном случае возвращает FALSE.

Если установлен FILTER_NULL_ON_FAILURE, FALSE возвращается только для «0», «false», «off», «no» и «», а NULL возвращается для всех небулевых значений.

Эрик Кэрон
источник
Это должен был быть принятый ответ. Встроенные функции PHP лучше, чем собственные. Не нужно изобретать велосипед! Жаль, что было слишком поздно: P
casraf
1
это также строчные буквы для сравнения?
Mobiletainment
3
@Mobiletainment, да - он обрабатывает любую оболочку, которую вы можете вообразить для значения $ (false, FALSE, FalSe и т. Д.)
Эрик Карон,
Тестовый набор на моем конце. Используется == вместо === для сравнения. Удаляю свой предыдущий комментарий, чтобы не запутывать людей.
andig
6
Ответ застал меня врасплох, потому что вы должны добавить флаг FILTER_NULL_ON_FAILUREк filter_var()функции, а НЕ заменять его, FILTER_VALIDATE_BOOLEANкак я думал. Это приведет к следующему коду, который $bool = filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE)
помог
14

Причина в том, что trueпри преобразовании в логическое значение все строки оцениваются как, кроме "0"и ""(пустая строка).

Следующая функция будет делать именно то, что вы хотите: она ведет себя точно так же, как PHP, но также оценивает строку "false"как false:

function isBoolean($value) {
   if ($value && strtolower($value) !== "false") {
      return true;
   } else {
      return false;
   }
}

В документации поясняется следующее: http://php.net/manual/en/language.types.boolean.php :

При преобразовании в логическое значение следующие значения считаются ЛОЖНЫМИ:

  • само логическое FALSE
  • целое число 0 (ноль)
  • поплавок 0,0 (ноль)
  • пустая строка и строка "0"
  • массив с нулевыми элементами
  • специальный тип NULL (включая неустановленные переменные)
  • Объекты SimpleXML, созданные из пустых тегов

Любое другое значение считается ИСТИННЫМ (включая любой ресурс).

Арно Ле Блан
источник
2
+1 Красиво. (Можно было бросить туда strtolower, но не более того.)
Джон Паркер
Я думаю, что миддапарка имела в виду сравнение strtolower ($ value) с false. Передавать буквальное «false» в strtolower - это немного .... глупо? :)
Пол Диксон
@ Пол Диксон Ага, это то, о чем я имел в виду. :-)
Джон Паркер
2
@Marco - if ($ value && strtolower ($ value)! == "faux") {если вы работаете на французском; if ($ value && strtolower ($ value)! == "falsch") {на немецком; if ($ value && strtolower ($ value)! == "onwaar") {на голландском ... вы можете понять, почему PHP не имеет этого в стандартной комплектации
Марк Бейкер
1
"все непустые строки имеют значение true при преобразовании их в логическое значение, кроме" 0 ".
BoltClock
5

Только в PHP "0"или принуждение пустой строки к false; каждая другая непустая строка приводится к истине. Из руководства :

При преобразовании в логическое значение учитываются следующие значения FALSE:

  • пустая строка и строка «0»

Вы должны написать свою собственную функцию для обработки строк "true"против "false". Здесь я предполагаю, что все остальное по умолчанию равно false:

function isBoolean($value) {
   if ($value === "true") {
      return true;
   } else {
      return false;
   }
}

На стороне примечания, которое можно легко сжать до

function isBoolean($value) {
   return $value === "true";
}
BoltClock
источник
4

Недавно мне понадобилась «свободная» функция логического преобразования для обработки строк, подобных тем, о которых вы спрашиваете (среди прочего). Я нашел несколько разных подходов и придумал большой набор тестовых данных для их обработки . Ничего не подходило под мои нужды, поэтому я написал свое:

function loosely_cast_to_boolean($value) {
    if(is_array($value) || $value instanceof Countable) {
        return (boolean) count($value);
    } else if(is_string($value) || is_object($value) && method_exists($value, '__toString')) {
        $value = (string) $value;
        // see http://www.php.net/manual/en/filter.filters.validate.php#108218
        // see https://bugs.php.net/bug.php?id=49510
        $filtered = filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
        if(!is_null($filtered)) {
            return $filtered;
        } else {
            // "none" gets special treatment to be consistent with ini file behavior.
            // see documentation in php.ini for more information, in part it says: 
            // "An empty string can be denoted by simply not writing anything after 
            // the equal sign, or by using the None keyword".
            if(strtolower($value) === 'none') {
                $value = '';
            }
            return (boolean) $value;
        }
    } else {
        return (boolean) $value;
    }
}

Обратите внимание, что для объектов, которые являются как счетными, так и строковыми, это предпочтет счетчику над строковым значением для определения истинности. То есть, если $object instanceof Countableэто вернется (boolean) count($object)независимо от значения (string) $object.

Вы можете увидеть поведение для тестовых данных , которые я использовал, а также результаты для ряда других функций здесь . Трудно просмотреть результаты этого маленького iframe, поэтому вместо этого вы можете просматривать вывод скрипта на полной странице (этот URL-адрес недокументирован, поэтому это может не работать вечно). На тот случай, если эти ссылки когда-нибудь умрут, я также помещаю код на pastebin .

Граница между тем, что «должно быть правдой» и что не должно, довольно условна; данные, которые я использовал, сгруппированы в зависимости от моих потребностей и эстетических предпочтений, ваши могут отличаться.

Мэтт Кантор
источник
Эта функция работает безотказно, спасибо! Но ваши ссылки теперь 404.
servermanfail
3

Я использую эту конструкцию для преобразования строк в логические значения, так как вы хотите trueдля большинства других значений:

$str = "true";
$bool = !in_array($str, array("false", "", "0", "no", "off"));
марио
источник
1

Есть ли в PHP функция для преобразования "истинных" и "ложных" строк в логические?

Нет - оба являются строками, и оба (как вы говорите) оценивают true. В falsePHP оцениваются только пустые строки .

Вам нужно будет проверить это вручную. Однако, если это вообще возможно, было бы лучше работать с «настоящими» логическими значениями.

Пекка
источник
1
Не все строки оцениваются trueв PHP.
Coreyward
1
Не исправлял, а просто уточнял. Высказывание «оба являются строками [и оценивают в true]» может создать у новичка неверное впечатление, особенно если речь идет о другом языке с более строгими правилами ввода, где строка является строкой, а содержимое не имеет значения, когда оно преобразуется в логическое значение (например, Рубин).
Coreyward
1
«Только пустые строки в PHP считаются ложными». А как насчет непустой строки "0"? Разве это тоже не оценивается false?
Сепстер,
0

Самый простой способ безопасно преобразовать в логическое значение;

    $flag = 'true';

    if( filter_var( $flag,FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE ) !== null) {
      $flag = filter_var($flag,FILTER_VALIDATE_BOOLEAN);
    }

    gettype($flag); // Would Return 'Boolean'
    echo 'Val: '.$flag; // Would Output 'Val: 1'
Тимоти Перес
источник
0

Если ваш API принимает только строки «истина» или «ложь», а все остальное становитсяnull , попробуйте:

$boolean = ['true' => true, 'false' => false][$inputString] ?? null;

Это предполагает, что $inputэто не объект. Null coalesce ( ??) был представлен в PHP 7.0.

Мэтт Янссен
источник