septembre
2007
C’est un sujet largement abordé lors du passage de la certification, il n’est pas complexe, mais il y a des notions qu’il faut maitriser.
PHP est faiblement typé. Sans répéter la documentation officielle, je vais rester concis et peut-être en faire gamberger certains, je vais faire un point général sur les règles de transtypage(appelé aussi ‘cast’) en PHP, et sur les comparaisons.
l’opérateur == compare 2 entités, pour cela il faut qu’elles soient du même type, et c’est bien là qu’une tonne d’astuces est à mémoriser.
Je parlerais après de l’opérateur d’identité ===
- Si je compare une chaine à un nombre, la chaine est implicitement castée en nombre
- Si je compare 2 chaines représentants des nombres, elles sont implicitement castées comme des nombres
- Un nombre est un entier, si il n’a pas de partie décimale, un nombre peut donc être un entier, ou un décimal (contenant donc un . ou un e, pour exposant)
- Si je compare un booléen ou la valeur NULL à n’importe quoi, le cast se fait vers le booléen
- Si je compare un tableau à une chaine ou un nombre, le tableau est toujours supérieur, il n’y a pas de cast implicite
- Si je compare un objet à une chaine ou un nombre, l’objet est systématiquement supérieur, il n’y a pas de cast implicite
- L’objet est supérieur au tableau, quels qu’ils soient.
Le cast fonctionne comme ceci :
null, 0, ‘0’ et « » valent false
false est casté en » pour la chaine, et 0 pour l’entier
un objet vaut toujours true (PHP5)
un array vaut true s’il est non vide
un array vaut l’entier 1, s’il est non vide, 0 sinon
un objet donne une erreur en le castant en string, s’il n’a pas de méthode __tostring()
un objet vers un entier passe par la string
la chaine si elle commence par un nombre, vaut ce nombre
la chaine si elle représente un nombre flottant, vaut la partie entière de ce nombre, lors du cast en entier (il n’y a pas d’arrondi!)
Il est très intéréssant de noter ceci :
000e0024785073 == « 0e22541f857″ // true : le chaine est convertie en nombre, et 0 == 0
« 000e0024785073″ == « 0e22541f857″ // false : la chaine de droite ne représente pas la syntaxe correcte d’un nombre, PHP compare donc 2 strings ici
« 000e0024785073″ == « 00f225418578″ // false : idem
array(‘2′) == 2 // false
‘2’ == 2 // true
10 == « 10.0 » // true
10 == « 10.0e00″ // true
10 == « 10.0e001″ // false
new StdClass == array() // false
$a = new StdClass; $a->a = 1; $a == array(‘a’=>1); // false
false == array(0); // false(int)array(2) == 2 // false
(int)array(null) == 0 // false
(int)array() == 0 // truearray(3) == 8 // false
Regardez cette « contre logique », mais qui suit bien les règles énoncées plus haut :
array() == 0 // false : un tableau est supérieur à un entier
array() == null // true : un tableau vide vaut false, null vaut false , et false == false
null == 0 // true : null vaut false, 0 vaut false
null == » // true : idemarray(1) == true // true, le tableau est converti vers un le booléen, il est non vide, il vaut donc true
new StdClass == true // true, l’objet est converti en booléen, et un objet vide vaut true en PHP5, pas en PHP4
(array)true == 1 // false, true est converti en array, et un array face à un entier est toujours supérieur
(int)(array)2 == 2 // false, l’entier 2 est converti en array, mais un array convertit en entier vaut toujours 1, sauf s’il est vide, or 1 n’est pas égal à 2
Regardez encore :
array(3,4,null) == 1 // false : un array est supérieur à un entier
(int)array(3,4,null) == 1 // true : un array vaut 1 lorsque non vide, et 1 == 1
Continuons un peu :
new StdClass == array() // false : un objet est supérieur à un array
new StdClass > « 2 » // true : l’objet est supérieur à l’entier
(string)new StdClass > « 2 » // error : stdClass n’a pas de méthode __tostring() déclarée (implicitement).
array() > 0 //true : idem
new stdClass > null // true : Ici la conversion se fait en booléen, un objet vaut true, et null vaut false, true est supérieur à false.
La certification ne donne pas de cas très complexes, en général, c’est un string contre un entier, et éventuellement la string contient un ‘E’, ou alors l’entier commence par 0 (octal)…
Néanmoins, nous venons de voit qu’il y a des subtilités qu’il faut connaitre, et nous n’avons parlé que de l’opérateur de comparaison, double égal, et pas des opérateurs de bits (&), ou booléens (&&)…
Un petit mot sur l’identité ===
2 opérandes sont identiques (===), s’ils sont égaux en valeur ET en type. Il n’y a pas trop de gotcha! au niveau des strings ou des nombres, en revanche il faut mémoriser pour les objets et les tableaux, que :
- 2 objets sont identiques s’ils pointent vers la même instance
- 2 tableaux sont identiques s’ils contiennent les mêmes paires clés/valeurs dans le même ordre et du même type
array(‘a’,’b’,’2′) === array(‘a’,’b’,2) // false car ‘2’ n’est pas identique à 2.
array(0=>’a’,1=>’b’) === array(1=>’b’,0=>’a’) // false, les valeurs n’ont pas été insérées dans le même ordre
array(‘0’=>’a’,1=>’b’) === array(0=>’a’,’1’=>’b’) // true, les clés string représentant des numériques sont converties implicitement en numérique
new stdClass === new stdClass // false, il ne s’agit pas de la même instance
2 Commentaires + Ajouter un commentaire
Commentaires récents
Archives
- novembre 2010
- août 2010
- juillet 2010
- juin 2010
- mai 2010
- avril 2010
- mars 2010
- février 2010
- janvier 2010
- décembre 2009
- novembre 2009
- octobre 2009
- septembre 2009
- août 2009
- juillet 2009
- juin 2009
- mai 2009
- avril 2009
- mars 2009
- février 2009
- janvier 2009
- décembre 2008
- novembre 2008
- octobre 2008
- septembre 2008
- août 2008
- juillet 2008
- juin 2008
- mai 2008
- avril 2008
- mars 2008
- février 2008
- janvier 2008
- décembre 2007
- novembre 2007
- octobre 2007
- septembre 2007
- août 2007
- juillet 2007
- juin 2007
- mai 2007
- avril 2007
- mars 2007
- février 2007
Oui j’ai fait une petite erreur, cependant :
Notice: Object of class Classe could not be converted to int in PHPDocument1 on line 4
PHP retourne 1, oui, mais génère une erreur. On retiendra donc qu’un objet ne peut être converti (proprement) vers un entier.
echo (int)new Stdclass;
Affiche effectivement 1, mais avec une erreur, il faut donc bannir ce transtypage et donc, ce type de comparaison.
Bonjour,
petite précision
« Si je compare un objet à une chaine ou un nombre, l’objet est systématiquement supérieur »
Il semble que l’objet soit casté en 1 en cas de comparaison avec un nombre
Class Classe {}
echo (new Classe() > 5)? « true »: »false »; // affiche false