On va également pouvoir comparer des variables objets de manière similaire, ce qui va pouvoir être très utile pour s’assurer par exemple qu’un objet est unique.
Principe de la comparaison d’objets
Pour comparer deux variables objets entre elles, nous allons à nouveau devoir utiliser des opérateurs de comparaison. Cependant, étant donné que les valeurs comparées vont cette fois-ci être des valeurs complexes (car un objet est composé de diverses propriétés et méthodes), nous n’allons pas pouvoir utiliser ces opérateurs de comparaison aussi librement que lors de la comparaison de valeurs simples.
La première chose à savoir est qu’on ne va pouvoir tester que l’égalité (en valeur ou en identité) entre les objets. En effet, cela n’aurait aucun sens de demander au PHP si un objet est « inférieur » ou « supérieur » à un autre puisqu’un objet regroupe un ensemble de propriétés et de méthodes.
En utilisant l’opérateur de comparaison simple ==
, les objets vont être considérés comme égaux s’ils possèdent les mêmes attributs et valeurs (valeurs qui vont être comparées à nouveau avec ==
et si ce sont des instances de la même classe.
En utilisant l’opérateur d’identité ===
, en revanche, les objets ne vont être considérés comme égaux que s’ils font référence à la même instance de la même classe.
Comparer des objets en pratique
Pour illustrer la façon dont le PHP va comparer différents objets et pour commenter les résultats renvoyés, nous allons nous baser sur l’exemple suivant :
<!DOCTYPE html> <html> <head> <title>Cours PHP & MySQL</title> <meta charset="utf-8"> <link rel="stylesheet" href="cours.css"> </head> <body> <h1>Titre principal</h1> <?php class Utilisateur{ protected $nom; public function __construct($n){ $this->nom = $n; } public function __clone(){ $this->nom = $this->nom. ' (clone)'; } public function getNom(){ echo $this->nom; } } $pierre = new Utilisateur('Pierre'); $pierre2 = new Utilisateur('Pierre'); $jean = $pierre; $victor = clone $pierre; echo 'Egalité simple entre $pierre et $pierre2 ? '; var_dump($pierre == $pierre2); echo '<br>Identité entre $pierre et $pierre2 ? '; var_dump($pierre === $pierre2); echo '<br><br>Egalité simple entre $pierre et $jean ? '; var_dump($pierre == $jean); echo '<br>Identité entre $pierre et $jean ? '; var_dump($pierre === $jean); echo '<br><br>Egalité simple entre $pierre et $victor ? '; var_dump($pierre == $victor); echo '<br>Identité entre $pierre et $victor ? '; var_dump($pierre === $victor); ?> <p>Un paragraphe</p> </body> </html>
Ici, on réutilise notre classe Utilisateur
créée précédemment. Cette classe définit une propriété $nom
ainsi qu’un constructeur qui va initialiser notre propriété, une méthode getNom()
dont le rôle est de renvoyer la valeur de $nom
de l’objet courant et une méthode __clone()
qui va mettre à jour la valeur de la propriété $nom
d’un clone.
On instancie ensuite deux fois notre classe Utilisateur
et on stocke le résultat dans deux variables objet $pierre
et $pierre2
.
En dessous, on assigne le contenu de $pierre
dans une nouvelle variable objet $jean
. Je vous rappelle ici que nos deux objets contiennent deux copies d’un identifiant pointant vers le même objet (la même instance de la classe).
Finalement, on crée un clone de $pierre
grâce au mot clef clone
qu’on appelle $victor
. Ici, une véritable copie de l’objet est créée et donc nos deux variable objets vont bien représenter deux instances différentes et indépendantes de la classe. Dès que le clonage est terminé, notre méthode __clone()
est appelée et la valeur de $nom
de $victor
est mise à jour.
L’idée va alors ici être de comparer nos différents objets. Pour cela, on utilise les opérateurs de comparaison ==
et ===
qui renvoient 1 si la comparaison réussit ou 0 si la comparaison échoue. On passe la valeur renvoyée à la fonction var_dump()
afin qu’elle nous renvoie le type de résultat (la valeur 1 correspond au booléen true
tandis que 0 correspond à false
.
La première comparaison simple entre $pierre
et $pierre2
réussit. En effet, nos deux objets sont issus de la même classe et leur propriété $nom
contient la même valeur puisqu’on a passé « Pierre » au constructeur dans les deux cas.
En revanche, la comparaison en termes d’identité échoue. La raison est que nos deux objets ont été créés en instanciant la classe à chaque fois et représentent donc deux instances différentes de la classe.
Cela n’est pas le cas pour notre objet $jean
qui contient la copie d’un identifiant pointant vers le même objet (la même instance de la classe) que $pierre
et qui va donc pouvoir être comparé à $pierre
en termes d’identité avec succès.
Notre dernier objet, $victor
, est un clone (ou une copie) de $pierre
et stocke donc une instance différente de $pierre
. De plus, juste après que le clonage ait été terminé, la valeur de $nom
du clone a été mise à jour. La comparaison entre $victor
et $pierre
échoue donc à la fois en termes d’identité et en termes de comparaison simple.