Aujourd’hui j’ai fini le cours de PHP 5 sur Developpez.com consacré au PHP objet. Il y a encore quelques trucs que je détaillerai dans les billets des prochains jours, mais en somme, mis à part mon problème avec self
et parent
, je pense avoir compris l’essentiel. Il se trouve que je suis actuellement en stage et que je vais avoir l’occasion de me confronter au framework maison de la boîte où je travaille, et, ô miracle, c’est un framework objet ! Il a l’air bigrement complet et bien fichu, mais aussi peut-être un petit peu compliqué pour moi… ça va être l’occasion de voir ce que j’ai compris ! Mais bref… parlons un peu de l’instanciation d’une classe et clonage d’objets.
Instanciation d’une classe et destruction d’objets
Lorsqu’on instancie une classe avec le mot clé new
, on créé une référence de cette instanciation. Et si on fait une copie de cet objet avec le symbole =
, on créé une nouvelle référence vers cette instanciation. Or pour supprimer une instanciation d’une classe, avec la fonction unset()
, il faut que toutes les références de cette classe soient supprimées. Pour bien comprendre, reprenons l’exemple de Développez.com. Pour cela, il faut savoir que la méthode magique __destruct()
est déclenchée lorsqu’on supprime une instance d’une classe.
<?php class Blog { function __destruct() { echo 'Je me meurs !'; } } $monBlog = new Blog(); $monAutreBlog = $monBlog; echo 'Allons soldats, tuons monBlog !'; unset($monBlog); echo 'Puisqu\'il résiste, éliminons donc son frère !'; unset($monAutreBlog);
Cet exemple affichera :
Allons soldats, tuons monBlog ! Puisqu'il résiste, éliminons donc son frère ! Je me meurs !
Et pourquoi ne pas cloner
Au lieu d’utiliser le symbole =
, on peut aussi utiliser le mot clé clone
pour signifier que l’on fait une nouvelle instanciation de la classe. La référence qui est créée vers cette instanciation n’a donc plus rien à voir avec la première. Le résultat du code suivant devient alors évident :
<?php class Blog { function __destruct() { echo 'Je me meurs !'; } } $monBlog = new Blog(); $monAutreBlog = clone $monBlog; echo 'Allons soldats, tuons monBlog !'; unset($monBlog); echo 'Continuons sur notre lancée, éliminons donc son frère !'; unset($monAutreBlog);
Cet exemple affichera :
Allons soldats, tuons monBlog ! Je me meurs ! Continuons sur notre lancée, éliminons donc son frère ! Je me meurs !
Résumons et clarifions
- … = … : créé une nouvelle référence vers l’objet -> Si on modifie l’objet les deux instances sont donc modifiées
- … = clone … : créé un nouvel objet -> Si on modifie l’un des deux objets, cela ne modifie pas l’autre
Un dernier petit exemple pour se fixer les idées :
<?php class Blog { var $nom; } $monBlog = new Blog(); $monBlog->nom = 'Bnbox !'; echo 'Valeur de $monBlog initialisée<br />'; echo '$monBlog : '.$monBlog->nom.'<br />'; $monAutreBlog = $monBlog; $tonBlog = clone $monBlog; echo '$monAutreBlog : '.$monAutreBlog->nom.'<br />'; echo '$tonBlog : '.$tonBlog->nom.'<br />'; echo '<br />Valeur de $monBlog modifiée<br />'; $monBlog->nom = '30 minutes par jour'; echo '$monBlog : '.$monBlog->nom.'<br />'; echo '$monAutreBlog : '.$monAutreBlog->nom.'<br />'; echo '$tonBlog : '.$tonBlog->nom.'<br />'; echo '<br />Valeur de $monAutreBlog modifiée<br />'; $monAutreBlog->nom = 'Bible Ipsum'; echo '$monBlog : '.$monBlog->nom.'<br />'; echo '$monAutreBlog : '.$monAutreBlog->nom.'<br />'; echo '$tonBlog : '.$tonBlog->nom.'<br />'; echo '<br />Valeur de $tonBlog modifiée<br />'; $tonBlog->nom = 'Flamb\'clair'; echo '$monBlog : '.$monBlog->nom.'<br />'; echo '$monAutreBlog : '.$monAutreBlog->nom.'<br />'; echo '$tonBlog : '.$tonBlog->nom.'<br />';
Ce qui affichera :
Valeur de $monBlog initialisée $monBlog : Bnbox ! $monAutreBlog : Bnbox ! $tonBlog : Bnbox ! Valeur de $monBlog modifiée $monBlog : 30 minutes par jour $monAutreBlog : 30 minutes par jour $tonBlog : Bnbox ! Valeur de $monAutreBlog modifiée $monBlog : Bible Ipsum $monAutreBlog : Bible Ipsum $tonBlog : Bnbox ! Valeur de $tonBlog modifiée $monBlog : Bible Ipsum $monAutreBlog : Bible Ipsum $tonBlog : Flamb'clair
Bref le clonage n’est vraiment pas qu’une question de référence 😀