Analyse d'une chaîne en une valeur booléenne en PHP

126

Aujourd'hui, je jouais avec PHP, et j'ai découvert que les valeurs de chaîne "true" et "false" ne sont pas correctement analysées en booléen dans une condition, par exemple en considérant la fonction suivante:

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

Si j'exécute:

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

Cela ne semble fonctionner qu'avec les valeurs "1" et "0":

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

Existe-t-il une fonction native en PHP pour analyser les chaînes "true" et "false" en booléen?

marque
la source
Dans votre code, isBoolean("")doit retourner false.
BoltClock
Vous devriez envisager de changer la réponse acceptée par celle d'Eric Caron. Il vous montre une fonction native qui fait ce que vous demandez.
Code Commander
1
PHP ne pense pas à ce que dit la chaîne, "false" est juste cinq caractères qui ne veulent rien dire. Ils sont cependant quelque chose , donc la valeur booléenne évalue truemême si pour un lecteur humain, cela semblerait plus intuitif que cela signifiait FALSE.
zeel

Réponses:

413

Il existe une méthode PHP native pour faire cela qui utilise la méthode filter_var de PHP:

$bool = filter_var($value, FILTER_VALIDATE_BOOLEAN);

Selon le manuel de PHP :

Renvoie TRUE pour "1", "true", "on" et "yes". Renvoie FALSE dans le cas contraire.

Si FILTER_NULL_ON_FAILURE est défini, FALSE est renvoyé uniquement pour "0", "false", "off", "no" et "", et NULL est renvoyé pour toutes les valeurs non booléennes.

Eric Caron
la source
Cela aurait dû être la réponse acceptée. Les fonctions PHP intégrées sont meilleures que de créer les vôtres. Pas besoin de réinventer la roue! Dommage qu'il soit trop tard: P
casraf
1
la valeur de la comparaison est-elle également minuscule?
Mobiletainment
3
@Mobiletainment, oui - il gère tous les boîtiers que vous pouvez imaginer pour $ value (false, FALSE, FalSe, etc.)
Eric Caron
Testcase Borked de mon côté. Utilisé == au lieu de === pour la comparaison. Va supprimer mon commentaire précédent pour ne pas confondre les gens.
andig
6
La réponse m'a pris au dépourvu car vous devez ajouter le drapeau FILTER_NULL_ON_FAILUREà la filter_var()fonction et ne PAS le remplacer par FILTER_VALIDATE_BOOLEANcomme je le pensais. Il en résultera le code suivant qui a fait l'affaire pour moi:$bool = filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE)
Dragon54
14

La raison est que toutes les chaînes sont évaluées truelors de leur conversion en booléen, sauf "0"et ""(chaîne vide).

La fonction suivante fera exactement ce que vous voulez: elle se comporte exactement comme PHP, mais évaluera également la chaîne "false"comme false:

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

La documentation explique que: http://php.net/manual/en/language.types.boolean.php :

Lors de la conversion en booléen, les valeurs suivantes sont considérées comme FAUX:

  • le booléen FALSE lui-même
  • l'entier 0 (zéro)
  • le flotteur 0.0 (zéro)
  • la chaîne vide et la chaîne "0"
  • un tableau avec zéro élément
  • le type spécial NULL (y compris les variables non définies)
  • Objets SimpleXML créés à partir de balises vides

Toute autre valeur est considérée comme TRUE (y compris toute ressource).

Arnaud Le Blanc
la source
2
+1 Nice. (Pourrait jeter un strtolower là-dedans, mais c'est à peu près tout.)
John Parker
Je pense que middaparka signifiait comparer strtolower ($ value) avec «false». Passer un «faux» littéral dans strtolower est un peu ... idiot? :)
Paul Dixon
@Paul Dixon Yup, c'est ce à quoi je faisais référence. :-)
John Parker
2
@Marco - if ($ value && strtolower ($ value)! == "faux") {si vous travaillez en français; if ($ value && strtolower ($ value)! == "falsch") {en allemand; if ($ value && strtolower ($ value)! == "onwaar") {en néerlandais ... vous pouvez comprendre pourquoi PHP ne l'a pas intégré en standard
Mark Baker
1
"toutes les chaînes non vides sont évaluées à vrai lors de leur conversion en booléen, sauf" 0 "."
BoltClock
5

En PHP uniquement "0"ou la chaîne vide contraint à false; toute autre chaîne non vide contraint à true. À partir du manuel :

Lors de la conversion en booléen, les valeurs suivantes sont prises en compte FALSE:

  • la chaîne vide et la chaîne "0"

Vous devez écrire votre propre fonction pour gérer les chaînes "true"vs "false". Ici, je suppose que tout le reste est par défaut faux:

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

Sur une note latérale qui pourrait facilement être condensée en

function isBoolean($value) {
   return $value === "true";
}
BoltClock
la source
4

J'ai récemment eu besoin d'une fonction de conversion booléenne "lâche" pour gérer des chaînes comme celles que vous demandez (entre autres). J'ai trouvé quelques approches différentes et suis venu avec un grand ensemble de données de test pour les parcourir . Rien ne correspondait tout à fait à mes besoins alors j'ai écrit le mien:

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;
    }
}

Notez que pour les objets qui sont à la fois dénombrables et convertibles en chaîne, cela favorisera le décompte par rapport à la valeur de chaîne pour déterminer la véracité. Autrement dit, si $object instanceof Countablecela reviendra (boolean) count($object)quelle que soit la valeur de (string) $object.

Vous pouvez voir le comportement des données de test que j'ai utilisées ainsi que les résultats de plusieurs autres fonctions ici . Il est un peu difficile de parcourir les résultats de cette petite iframe, donc vous pouvez afficher la sortie du script dans une page complète , à la place (cette URL n'est pas documentée, donc cela pourrait ne pas fonctionner éternellement). Au cas où ces liens meurent un jour, je mets également le code sur pastebin .

La ligne entre ce qui «devrait être vrai» et ce qui ne devrait pas est assez arbitraire; les données que j'ai utilisées sont classées en fonction de mes besoins et de mes préférences esthétiques, les vôtres peuvent différer.

Matt Kantor
la source
Cette fonction fonctionne parfaitement, merci! Mais vos liens sont maintenant 404.
servermanfail
3

J'utilise cette construction pour transformer les chaînes en booléens, puisque vous voulez truepour la plupart des autres valeurs:

$str = "true";
$bool = !in_array($str, array("false", "", "0", "no", "off"));
mario
la source
1

Existe-t-il une fonction en PHP pour analyser les chaînes "true" et "false" en booléen?

Non - les deux sont des chaînes, et ces deux (comme vous le dites) évaluent à true. Seules les chaînes vides sont évaluées falseen PHP.

Vous auriez besoin de tester cela manuellement. Dans la mesure du possible, cependant, il serait préférable de travailler avec des valeurs booléennes «réelles» à la place.

Pekka
la source
1
Toutes les chaînes ne sont pas évaluées trueen PHP.
coreyward
1
Ce n'était pas une correction, juste une clarification. Dire "les deux sont des chaînes [et évaluer à true]" peut donner une mauvaise impression au débutant, en particulier celui d'une autre langue avec des règles de frappe plus strictes où une chaîne est une chaîne et le contenu n'a pas d'importance lorsqu'il est converti en booléen (comme Rubis).
coreyward
1
"Seules les chaînes vides donnent la valeur false en PHP." Mais qu'en est-il de la chaîne non vide "0"? Cela ne vaut-il pas également false?
Sepster
0

Le moyen le plus simple de convertir en toute sécurité un booléen;

    $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'
Timothy Perez
la source
0

Si votre API n'accepte que les chaînes "true" ou "false", tout le reste devenantnull , alors essayez:

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

Cela suppose que ce $inputn'est pas un objet. Null coalesce ( ??) a été introduit dans PHP 7.0.

Matt Janssen
la source