Pourquoi PHP traite "0" comme FAUX dans des contextes booléens?

12

"0", en tant que chaîne contenant un caractère, n'est pas quelque chose de vide intuitivement. Pourquoi PHP le traite-t-il comme FAUX lorsqu'il est converti en booléen, contrairement à d'autres langages de programmation?

Michael Tsang
la source
2
duplicata de: stackoverflow.com/questions/523643/… . C'est la même chose en PHP et en javascript vérifiez la réponse ci-dessous la réponse acceptée.
Walfrat
5
C'est parce que PHP s'efforce d'être aussi incohérent, avec lui-même et avec tous les autres langages de programmation, que possible.
David Arno
2
@DavidArno Au contraire, il fait de son mieux pour être cohérent ; une fois que vous commencez la diffusion automatique de chaînes (très pratique dans une langue qui récupère souvent les variables des URL ou des corps de requête), vous devez suivre cette logique. Si '0'est traité comme 0dans $x + 1, pourquoi ne devrait-il pas également être traité comme 0, et donc false, dans if ( $x )?
IMSoP
1
@DavidArno exactement;)
linuxunil
1
@DavidArno Une fois que vous commencez à effectuer des conversions avec perte, une certaine incohérence est inévitable, je pense; la solution cohérente consiste à rejeter certains modèles et à concevoir le reste très soigneusement. Cependant, très peu de langues populaires sont conçues à partir de zéro; la plupart évoluent soit à partir d'expériences accidentellement populaires, soit à partir de langues plus anciennes avec des objectifs et des bagages différents. Même C #, qui a beaucoup de conception théorique solide, a un héritage de C, qui n'a jamais été conçu pour être aussi universel qu'il est devenu. Snark comme "aller trop loin pour être incohérent", c'est comme crier à l'arbitre lors d'un match de sport.
IMSoP

Réponses:

12

PHP a été conçu (ou, plutôt, évolué) pour être utilisé avec les requêtes Web, où vous traitez fréquemment des entrées de chaîne (paramètres d'URL ou requêtes POST à ​​partir d'un formulaire dans un navigateur). En tant que tel, il convertira automatiquement les chaînes en d'autres types.

Un exemple simple de ceci est que '1' + '2'donne 3, pas une erreur, ou '12', ou une autre interprétation. Selon la même logique, la chaîne '0'peut être utilisée sous forme numérique 0.

Pendant ce temps, comme de nombreux langages, PHP traite certaines valeurs comme "fausses" lorsqu'elles sont converties en booléens - celles qui sont intuitivement "vides", comme vous le dites. Cela inclut le numérique 0, ainsi que la chaîne vide ''et le tableau vide []. Dans une ifinstruction, l'expression est explicitement convertie en booléen, elle if ( 0 )est donc identique à if ( false ).

En combinant ces deux choses, vous obtenez une énigme: d'une part, comme vous le dites, il '0's'agit d'une chaîne non vide; d'autre part, nous avons dit qu'il peut être utilisé comme un numérique 0, qui est "vide". PHP choisit de traiter le "zéro-ness" comme plus important que la "stringence", de sorte que cela '0'est considéré comme "faux".

En bref '0' == 0 == false:; ou(bool)'0' === (bool)(int)'0'

IMSoP
la source
Est-ce que quelqu'un a mis ma réponse en échec juste parce que j'ai osé défendre PHP et répondre à la question avec autre chose qu'une plaisanterie bon marché et ignorante? Ou y a-t-il quelque chose d'inexact ou de inutile dans ma réponse qu'ils voudraient signaler?
IMSoP
1
Je pense que PHP a pris cela de Perl, qui a le même "0" comportement " est faux". En Perl, il n'y a littéralement aucune différence visible par l'utilisateur entre la chaîne "0"et le nombre 0- ennuyeux lors de la manipulation de JSON, mais très intuitif lors de la manipulation de données textuelles. Il est alors impossible que le nombre 0soit falsey sans que la chaîne "0"soit falsey. PHP et JavaScript emprunter cette décision de conception, mais ajoutent une certaine confusion en distinguant chaînes / bools / types numériques tout en permettant les conversions implicites (PHP: 0 == "0 foo", 0 == falsemais "0 foo" == true: ==n'est pas transitive)
amon
@amon Oui, Perl adopte l'approche intéressante de (presque) tous les opérateurs et fonctions intégrées forçant les opérandes à un type particulier, avec des opérateurs supplémentaires comme eqpour l'égalité des chaînes. Cependant, cela ne le sauve pas de la non-transitivité des "0 foo"lancers avec perte: est vrai dans un contexte booléen, mais est égal à 0under ==. Alors if ( ! $foo ) ..et $false = (1 == 2); if ( $foo == $false ) ... ne donnez pas le même résultat. Je suppose que le langage manque un opérateur "égalité booléenne" qui pourrait traiter cela de manière cohérente ...
IMSoP
Bien que "0" soit 0 lorsqu'il est évalué en tant que numérique, lorsque nous utilisons une chaîne dans un contexte booléen (par exemple dans une instruction if), nous ne sommes pas intéressés par sa valeur numérique. Si nous voulons l'interpréter comme numérique, nous le comparerions avec un certain nombre, par exemple $_POST['id'] == 0, ce qui indique clairement que nous voulons traiter l'entrée utilisateur comme un nombre.
Michael Tsang
1
@MestreLion Cet exemple concernait Perl plutôt que PHP. La différence cruciale étant qu'il n'y a pas de type booléen séparé en Perl, $falsefinit donc par être défini sur 0; donc quand vous écrivez $foo == $false, Perl ne sait pas que vous voulez une comparaison booléenne, et transforme en int à la place. En PHP, cela ne se produit pas, car $falsebooléen est faux, donc ==converti en booléen, donnant le même résultat que!
IMSoP
3

Selon la documentation PHP sur les booléens , il dit que:

Lors de la conversion en booléen, les valeurs suivantes sont prises en compte FALSE
...
la chaîne vide et la chaîne "0"
...

Autrement:

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

Si vous exécutez:

var_dump((bool) "0");

Il imprimera:

bool (faux)

Cela fonctionne donc comme prévu.


Pour répondre explicitement à votre question:

Cependant, dans la plupart des cas, la conversion n'est pas nécessaire, car une valeur sera automatiquement convertie si un opérateur, une fonction ou une structure de contrôle nécessite un argument booléen.

Cela signifie que la «diffusion automatique» de PHP transtypera «0» en entier 0, ce qui est FALSEégalement dans une structure de contrôle comme, par exemple, une if()instruction.

kayess
la source
Je voudrais connaître la justification de la décision de conception traitant le "0" comme FAUX lorsqu'il est converti en booléen, plutôt que la nécessité d'un casting explicite.
Michael Tsang