French (Français) translation by Cécile Angays (you can also view the original English article)
Pour beaucoup de programmeurs PHP, la programmation orientée objet est un concept obscur, rempli de syntaxes affreusement compliquées et de divers obstacles. Comme expliqué plus en détail dans mon livre, Pro PHP and jQuery, vous apprendrez ici les concepts de base de la programmation orientée objet (POO) , une manière de coder dans laquelle plusieurs actions sont regroupées dans une classe, pour permettre de créer un code plus efficace et plus compact.
Comprendre la Programmation Orientée Objet
L'orienté objet est une manière de coder qui permet aux développeurs de grouper des actions similaires en classes. Cela permet notamment de suivre un des adages principaux de la programmation : "Don't repeat Yourself" (DRY) , soit ne pas se répéter lorsque l'on peut grouper du code, et il est plus facile de le maintenir à jour.
"L'orienté objet est une manière de coder qui permet aux développeurs de grouper des actions similaires en classes."
Un des bénéfices majeurs de la programmation DRY (ne pas se répéter) est que s'il y a une information à changer dans votre programme, il n'y aurait qu'un seul changement à effectuer. Un des pire cauchemars pour un développeur est de maintenir un code où les données sont déclarées à plusieurs endroits différents, puis redéclarées encore, et encore, signifiant souvent que le moindre changement de ces données dans le programme devient alors une partie de "où est Charlie?" infiniment frustrante, où l'on chasse alors les données dupliquées dans les différentes fonctionnalités.
La POO semble compliquées pour beaucoup de développeurs, parce qu'elle inclut une nouvelle syntaxe, et , au premier abord, semble être beaucoup plus complexes que le procédural. Cependant, à y regarder de plus près, la POO est en fait une approche bien plus directe et simple pour la programmation.
Comprendre les Objets et les Classes
Avant de plonger plus profond dans les concepts les plus poussés de la POO, il est important de pouvoir différencier les objets et les classes. Dans cette section, nous définirons ce que sont les classes, leur différentes utilités et certains de leurs usages.
Reconnaître les Différences Entre Objets et Classes

Les développeurs parlent d'objets et de classes, en pensant que ces termes sont interchangeables. En fait... non. Pas du tout.
Dès le départ, il y a confusion dans la POO : les développeurs chevronnés commencent à parler de classes et d'objets, comme si ces termes étaient interchangeables. Alors qu'en fait... pas du tout! Mais il est vrai qu'au premier coup d'oeil, la différence peut être difficile à appréhender.
Une classe, par exemple, serait comme le plan d'une maison. Le plan permet de définir la forme de la maison sur du papier, où l'on peut y voir chaque pièce de la maison, ainsi que les liens entre elles (les portes, par exemple). Même si la maison n'existe pas, tout cela est déjà défini.
Un objet, si l'on suit cette comparaison, serait en fait la véritable maison, construite selon ce plan. Les données que l'on va intégrer dans l'objet sont par exemple le bois, les câbles, et tous les éléments concrets qui vont composer cette maison, et qui, sans le plan de la maison, ne seraient qu'une pile de matériaux inutiles. Et lorsque l'on combine ces matériaux avec le plan, on obtient alors une belle maison construite, organisée et utile.
Les classes forment en fait la structure des données et des actions et utilisent toute ces information pour construire des objets. A partir de là, on peut tout à fait construire plusieurs objets à partir d'une même classe, chaque objet étant indépendant des autres. En continuant sur l'analogie des constructions, c'est la même chose que lorsque tout un quartier est construit selon le même plan : 150 maisons, qui se ressemblent toutes, mais qui ont différents
familles et différentes décorations à l'intérieur.
Structurer une classe
La syntaxe de création d'une classe est assez simple : déclarez une classe en utilisant le mot-clé class
, suivi du nom que vous souhaitez donner à cette classe, et une paire d'accolades({}
):
<?php class MyClass { // Class properties and methods go here } ?>
Après avoir créé la classe, un nouvel objet peut être "instancié" depuis cette classe, et sera stocké dans une variable en utilisant le mot-clé new
:
$obj = new MyClass;
Pour voir le contenu de cette classe, utilisez var_dump()
:
var_dump($obj);
Testez donc tout cela, en rentrant les lignes de code précédemment données dans un nouveau fichier, test.php
dans votre dossier de test habituel pour le php.
<?php class MyClass { // Class properties and methods go here } $obj = new MyClass; var_dump($obj); ?>
Chargez la page dans votre navigateur à l'adresse http://localhost/test.php
et le texte suivant devrait s’afficher :
object(MyClass)#1 (0) { }
Félicitations, vous venez tout juste de réaliser votre premier script en POO, dans sa forme la plus simple.
Définir les propriétés d'une classe
Pour ajouter des données à une classe, on utilise des propriétés. En fait, ce sont des variables comme les autres, mais pour bien les différencier des variables hors classe, on les appelle des propriétés, et l'on ne peut y accéder qu'en utilisant les objets.
Pour ajouter une propriété à votre classe MyClass
, ajoutez ce bout de code à votre script:
<?php class MyClass { public $prop1 = "I'm a class property!"; } $obj = new MyClass; var_dump($obj); ?>
Le mot clé public
détermine la visibilité de la propriété, dont vous comprendrez les particularités un peu plus loin dans cet article. Ensuite, la variable est nommé selon les standards de nommage (en UpperCamelCase), puis on lui donne une valeur (cependant, les propriétés des classes n'ont pas besoin d'avoir une valeur de départ)
Pour lire cette propriété et l'afficher dans le navigateur, il faut référencer l'objet et la propriété qu'on veut lire de cette manière:
echo $obj->prop1;
Puisqu'il existe plusieurs instances(= maisons) d'une seule classe (= plan), si l'objet n'est pas référencé individuellement avec un nom qui lui est propre (ici $obj), le script sera incapable de déterminer de quel objet précisément il doit afficher la propriété (dois-je afficher la propriété de la maison1? de la maison 2?) L'utilisation de la flèche (->
) est une écriture spécifique de la POO, qui permet d'accéder aux propriétés et aux méthodes d'un objet donné.
Modifiez le script dans test.php
pour lire la propriété plutôt que de montrer la totalité de la classe comme on le faisait avec le dump, et écrivez plutôt ce qui suit:
<?php class MyClass { public $prop1 = "I'm a class property!"; } $obj = new MyClass; echo $obj->prop1; // Output the property ?>
Si vous rechargez votre navigateur, vous verrez maintenant s'afficher:
I'm a class property!
Définir les méthodes d'une classe
Les méthodes d'une classe sont en fait de simples fonctions, mais qu'on utilise dans des classes, et qui ne sont donc accessibles que via la classe à laquelle elles appartiennent. Les actions qu'un objet sera capable d'effectuer sont définies dans les classes en tant que méthodes.
Par exemple, pour créer des méthodes pour remplacer et obtenir la valeur de la propriété $prop1
, ajoutez ceci à votre code:
<?php class MyClass { public $prop1 = "I'm a class property!"; public function setProperty($newval) { $this->prop1 = $newval; } public function getProperty() { return $this->prop1 . "<br />"; } } $obj = new MyClass; echo $obj->prop1; ?>
Note — la POO permet aux objets de se référer à eux-même, en utilisant $this
. Lorsque l'on travaille dans une méthode, on peut alors utiliser $this
de la même manière que l'on utiliserait le nom de l'objet en dehors de la classe (c'est à dire qu'au final, au lieu d'écrire le nom de l'objet, on écrit $this).
Pour utiliser ces méthodes, il suffit de les appeler, comme des fonctions normales, mais en premier lieu, on référence d'abord sur quel objet elles interviennent. En faisant les modifications ci-dessous, vous allez donc accéder à la propriété issue de MyClass
, changer sa valeur, puis y accéder de nouveau:
<?php class MyClass { public $prop1 = "I'm a class property!"; public function setProperty($newval) { $this->prop1 = $newval; } public function getProperty() { return $this->prop1 . "<br />"; } } $obj = new MyClass; echo $obj->getProperty(); // Get the property value $obj->setProperty("I'm a new property value!"); // Set a new one echo $obj->getProperty(); // Read it out again to show the change ?>
Actualisez votre page dans le navigateur, et vous verrez apparaître ceci:
I'm a class property! I'm a new property value!
"Le pouvoir de la POO devient vraiment visible lorsque l'on utilise plusieurs instances à partir de
la même classe."
<?php class MyClass { public $prop1 = "I'm a class property!"; public function setProperty($newval) { $this->prop1 = $newval; } public function getProperty() { return $this->prop1 . "<br />"; } } // Create two objects $obj = new MyClass; $obj2 = new MyClass; // Get the value of $prop1 from both objects echo $obj->getProperty(); echo $obj2->getProperty(); // Set new values for both objects $obj->setProperty("I'm a new property value!"); $obj2->setProperty("I belong to the second instance!"); // Output both objects' $prop1 value echo $obj->getProperty(); echo $obj2->getProperty(); ?>
Lorsque vous actualisez de nouveau la page avec ce nouveau code dans votre navigateur, il sera lu ainsi:
I'm a class property! I'm a class property! I'm a new property value! I belong to the second instance!
Comme vous pouvez le voir, la POO sépare chaque objet en entités bien distinctes, ce qui rend beaucoup plus facile la séparation de différents morceaux de code pour les transformer en petits bundles.
Les Méthodes Magiques en POO
Pour faciliter l'utilisation des objets, PHP nous procure également un certain nombre de méthodes magiques, ou méthodes spéciales, qui sont appelées lorsque certaines actions assez communes sont faites avec un objet. Cela permet aux développeurs de réaliser un certain nombre de tâches très utiles de manière très facile.
Utiliser les Constructeurs et les Destructeurs
Lorsqu'un objet est instancié, on veut souvent le personnaliser un peu dès le début, pour le différencier des autres objets qui seront instanciés de la même classe. Pour permettre ceci, PHP inclut une méthode magique appelée __construct()
, qui sera appelée automatiquement dès qu'un nouvel objet sera
créé.
Pour bien vous illustrer le concept des constructeurs, ajoutez un constructeurs à votre classe MyClass
qui sortira un message dès qu'un nouvel objet sera créé à partir de la classe:
<?php class MyClass { public $prop1 = "I'm a class property!"; public function __construct() { echo 'The class "', __CLASS__, '" was initiated!<br />'; } public function setProperty($newval) { $this->prop1 = $newval; } public function getProperty() { return $this->prop1 . "<br />"; } } // Create a new object $obj = new MyClass; // Get the value of $prop1 echo $obj->getProperty(); // Output a message at the end of the file echo "End of file.<br />"; ?>
Note — __CLASS__
retourne le nom de la classe dans laquelle il est appelé ; C’est ce qu’on appelle une constante magique. Il y existe plusieurs constantes magiques, sur lesquelles vous pourrez apprendre dans le manuel PHP.
Actualisez le fichier dans votre navigateur pour obtenir le résultat suivant:
The class "MyClass" was initiated! I'm a class property! End of file.
Pour appeler une fonction quand un objet est détruit, on utilise la méthode magique __destruct()
. C'est assez utile pour nettoyer une classe (fermer une connexion à la base de donnée par exemple).
Quand l'objet est détruit, affichez un message en utilisant la méthode magique__destruct()
dans MyClass
:
<?php class MyClass { public $prop1 = "I'm a class property!"; public function __construct() { echo 'The class "', __CLASS__, '" was initiated!<br />'; } public function __destruct() { echo 'The class "', __CLASS__, '" was destroyed.<br />'; } public function setProperty($newval) { $this->prop1 = $newval; } public function getProperty() { return $this->prop1 . "<br />"; } } // Create a new object $obj = new MyClass; // Get the value of $prop1 echo $obj->getProperty(); // Output a message at the end of the file echo "End of file.<br />"; ?>
Avec un destructeur, quand vous actualiserez la page, vous verrez maintenant s'afficher ceci:
The class "MyClass" was initiated! I'm a class property! End of file. The class "MyClass" was destroyed.
"Lorsque PHP atteint la fin d'un fichier, il libère automatiquement toutes les ressources utilisées."
Pour utiliser explicitement le destructeur, vous pouvez détruire l'objet en utilisant la
fonction unset()
:
<?php class MyClass { public $prop1 = "I'm a class property!"; public function __construct() { echo 'The class "', __CLASS__, '" was initiated!<br />'; } public function __destruct() { echo 'The class "', __CLASS__, '" was destroyed.<br />'; } public function setProperty($newval) { $this->prop1 = $newval; } public function getProperty() { return $this->prop1 . "<br />"; } } // Create a new object $obj = new MyClass; // Get the value of $prop1 echo $obj->getProperty(); // Destroy the object unset($obj); // Output a message at the end of the file echo "End of file.<br />"; ?>
Maintenant le résultat change comme montré ci-dessous lorsque vous actualisez votre navigateur:
The class "MyClass" was initiated! I'm a class property! The class "MyClass" was destroyed. End of file.
Convertir en String (chaîne de caractère)
Pour éviter d'obtenir une erreur si un script tente d'appeler MyClass
en tant que chaîne de caractère, une autre méthode magique utilisée est __toString()
.
Sans le __toString()
, le fait d'essayer de sortir l'objet en tant que chaîne de caractère conduira à une erreur fatale! Par exemple, essaye d'utiliser echo
pour obtenir la valeur de l'objet sans la méthode magique:
<?php class MyClass { public $prop1 = "I'm a class property!"; public function __construct() { echo 'The class "', __CLASS__, '" was initiated!<br />'; } public function __destruct() { echo 'The class "', __CLASS__, '" was destroyed.<br />'; } public function setProperty($newval) { $this->prop1 = $newval; } public function getProperty() { return $this->prop1 . "<br />"; } } // Create a new object $obj = new MyClass; // Output the object as a string echo $obj; // Destroy the object unset($obj); // Output a message at the end of the file echo "End of file.<br />"; ?>
Le résultat sera le suivant:
The class "MyClass" was initiated! Catchable fatal error: Object of class MyClass could not be converted to string in /Applications/XAMPP/xamppfiles/htdocs/testing/test.php on line 40
Pour éviter cette erreur, ajoute donc une méthode __toString()
:
<?php class MyClass { public $prop1 = "I'm a class property!"; public function __construct() { echo 'The class "', __CLASS__, '" was initiated!<br />'; } public function __destruct() { echo 'The class "', __CLASS__, '" was destroyed.<br />'; } public function __toString() { echo "Using the toString method: "; return $this->getProperty(); } public function setProperty($newval) { $this->prop1 = $newval; } public function getProperty() { return $this->prop1 . "<br />"; } } // Create a new object $obj = new MyClass; // Output the object as a string echo $obj; // Destroy the object unset($obj); // Output a message at the end of the file echo "End of file.<br />"; ?>
Dans ce cas, convertir l'objet en chaîne de caractère amène à appeler la méthode getProperty()
. Rechargez le script dans votre navigateur pour voir le résultat.
The class "MyClass" was initiated! Using the toString method: I'm a class property! The class "MyClass" was destroyed. End of file.
Tip - En plus des méthodes magiques décrites ici, il en existe plusieurs autres. Pour voir la liste complète des méthodes magiques, référez vous à la page web de PHP manuel.
Utilisation des héritages de Classe
Les classes peuvent hériter de méthodes et propriétés d'une autre classe, en utilisant le mot clé extends
. Par exemple, pour créer une seconde classe qui serait l'extension de MyClass
et lui ajouter une méthode, vous pouvez ajouter ce code à votre fichier de test:
<?php class MyClass { public $prop1 = "I'm a class property!"; public function __construct() { echo 'The class "', __CLASS__, '" was initiated!<br />'; } public function __destruct() { echo 'The class "', __CLASS__, '" was destroyed.<br />'; } public function __toString() { echo "Using the toString method: "; return $this->getProperty(); } public function setProperty($newval) { $this->prop1 = $newval; } public function getProperty() { return $this->prop1 . "<br />"; } } class MyOtherClass extends MyClass { public function newMethod() { echo "From a new method in " . __CLASS__ . ".<br />"; } } // Create a new object $newobj = new MyOtherClass; // Output the object as a string echo $newobj->newMethod(); // Use a method from the parent class echo $newobj->getProperty(); ?>
En rechargeant le document dans votre navigateur, vous verrez donc ceci:
The class "MyClass" was initiated! From a new method in MyOtherClass. I'm a class property! The class "MyClass" was destroyed.
Réécrire des Propriétés et Méthodes héritées
Pour changer le comportement d'une propriété ou méthode existante dans la nouvelle classe, vous pouvez simplement la réécrire, en la déclarant de nouveau dans la nouvelle classe, avec exactement le même nom:
<?php class MyClass { public $prop1 = "I'm a class property!"; public function __construct() { echo 'The class "', __CLASS__, '" was initiated!<br />'; } public function __destruct() { echo 'The class "', __CLASS__, '" was destroyed.<br />'; } public function __toString() { echo "Using the toString method: "; return $this->getProperty(); } public function setProperty($newval) { $this->prop1 = $newval; } public function getProperty() { return $this->prop1 . "<br />"; } } class MyOtherClass extends MyClass { public function __construct() { echo "A new constructor in " . __CLASS__ . ".<br />"; } public function newMethod() { echo "From a new method in " . __CLASS__ . ".<br />"; } } // Create a new object $newobj = new MyOtherClass; // Output the object as a string echo $newobj->newMethod(); // Use a method from the parent class echo $newobj->getProperty(); ?>
A ce moment, le résultat dans le navigateur devient:
A new constructor in MyOtherClass. From a new method in MyOtherClass. I'm a class property! The class "MyClass" was destroyed.
Tout en préservant les autres méthodes de la classe héritée.
Pour ajouter une méthode déjà existante dans la méthode héritée (par exemple, un nouveau constructeur) sans écraser la méthode originale, utilisez le mot-clé parent
avec le double deux points (::
):
<?php class MyClass { public $prop1 = "I'm a class property!"; public function __construct() { echo 'The class "', __CLASS__, '" was initiated!<br />'; } public function __destruct() { echo 'The class "', __CLASS__, '" was destroyed.<br />'; } public function __toString() { echo "Using the toString method: "; return $this->getProperty(); } public function setProperty($newval) { $this->prop1 = $newval; } public function getProperty() { return $this->prop1 . "<br />"; } } class MyOtherClass extends MyClass { public function __construct() { parent::__construct(); // Call the parent class's constructor echo "A new constructor in " . __CLASS__ . ".<br />"; } public function newMethod() { echo "From a new method in " . __CLASS__ . ".<br />"; } } // Create a new object $newobj = new MyOtherClass; // Output the object as a string echo $newobj->newMethod(); // Use a method from the parent class echo $newobj->getProperty(); ?>
On obtiendra le résultat des deux constructeurs : celui de la classe parent(aussi appelé classe mère) et le nouveau constructeur (celui de la classe dite "fille").
The class "MyClass" was initiated! A new constructor in MyOtherClass. From a new method in MyOtherClass. I'm a class property! The class "MyClass" was destroyed.
Gérer la visibilité des Propriétés et Méthodes
Pour mieux les contrôler, les méthodes et propriétés des objets, on peut gérer leur visibilité. Cela permet de vérifier comment et à partir d'ou les propriétés et méthodes d'une classe sont accessibles. Il existe trois mots-clés pour la visibilité: public
, protected
, et private
. En plus de sa visibilité, une méthode ou propriété peut être déclarée comme static
, ce qui permet d'y accéder sans avoir besoin d'instancier un objet à partir de la classe.
Pour mieux les contrôler, les méthodes et propriétés des objets, on peut gérer leur visibilité.
Note - La visibilité est une nouvelle fonctionnalité de PHP 5. Pour des informations sur la compatibilité en POO avec PHP 4, référez vous à la page correspondante de PHP manuel.
Les Propriétés et Méthodes Publiques
Toutes les méthodes et propriétés que vous avez utilisées jusqu'à présent étaient publiques. Cela signifie que l'on peut y accéder à partir de n'importe où, que ce soit à l'intérieur ou à l'extérieur de la classe.
Les Propriétés et Méthodes Protégées
Quand une propriétés ou une méthode est déclarée protected
, on ne peut y accéder que dans la classe elle même ou bien dans des classes filles (classe étendues à partir d'une classe qui contient une méthode protégée).
Déclarez la méthode getProperty()
comme protégée, dans MyClass
, et essayez d'y accéder directement, à l'extérieur de la classe:
<?php class MyClass { public $prop1 = "I'm a class property!"; public function __construct() { echo 'The class "', __CLASS__, '" was initiated!<br />'; } public function __destruct() { echo 'The class "', __CLASS__, '" was destroyed.<br />'; } public function __toString() { echo "Using the toString method: "; return $this->getProperty(); } public function setProperty($newval) { $this->prop1 = $newval; } protected function getProperty() { return $this->prop1 . "<br />"; } } class MyOtherClass extends MyClass { public function __construct() { parent::__construct(); echo "A new constructor in " . __CLASS__ . ".<br />"; } public function newMethod() { echo "From a new method in " . __CLASS__ . ".<br />"; } } // Create a new object $newobj = new MyOtherClass; // Attempt to call a protected method echo $newobj->getProperty(); ?>
Mais si vous essayez de lancer le script, vous verrez le message suivant s'afficher:
The class "MyClass" was initiated! A new constructor in MyOtherClass. Fatal error: Call to protected method MyClass::getProperty() from context '' in /Applications/XAMPP/xamppfiles/htdocs/testing/test.php on line 55
Maintenant, créez une nouvelle méthode dans MyOtherClass
pour appeler la méthode getProperty()
:
<?php class MyClass { public $prop1 = "I'm a class property!"; public function __construct() { echo 'The class "', __CLASS__, '" was initiated!<br />'; } public function __destruct() { echo 'The class "', __CLASS__, '" was destroyed.<br />'; } public function __toString() { echo "Using the toString method: "; return $this->getProperty(); } public function setProperty($newval) { $this->prop1 = $newval; } protected function getProperty() { return $this->prop1 . "<br />"; } } class MyOtherClass extends MyClass { public function __construct() { parent::__construct(); echo "A new constructor in " . __CLASS__ . ".<br />"; } public function newMethod() { echo "From a new method in " . __CLASS__ . ".<br />"; } public function callProtected() { return $this->getProperty(); } } // Create a new object $newobj = new MyOtherClass; // Call the protected method from within a public method echo $newobj->callProtected(); ?>
Cela affiche alors le bon résultat:
The class "MyClass" was initiated! A new constructor in MyOtherClass. I'm a class property! The class "MyClass" was destroyed.
Les Propriétés et Méthodes Privées
Une propriété ou méthode déclarée private
est accessible uniquement à l'intérieur de sa classe, et plus à partir des classes filles. Cela signifie que même si cette classe est étendue vers une nouvelle classe (c'est à dire qu'elle devient la classe mère d'une autre classe), cette propriété ou méthode privée ne sera pas acccessible aux classes filles.
Mettons le en pratique en déclarant la méthode getProperty()
en privée dans MyClass
, et essayer donc d'appeler callProtected()
à partir deMyOtherClass
:
<?php class MyClass { public $prop1 = "I'm a class property!"; public function __construct() { echo 'The class "', __CLASS__, '" was initiated!<br />'; } public function __destruct() { echo 'The class "', __CLASS__, '" was destroyed.<br />'; } public function __toString() { echo "Using the toString method: "; return $this->getProperty(); } public function setProperty($newval) { $this->prop1 = $newval; } private function getProperty() { return $this->prop1 . "<br />"; } } class MyOtherClass extends MyClass { public function __construct() { parent::__construct(); echo "A new constructor in " . __CLASS__ . ".<br />"; } public function newMethod() { echo "From a new method in " . __CLASS__ . ".<br />"; } public function callProtected() { return $this->getProperty(); } } // Create a new object $newobj = new MyOtherClass; // Use a method from the parent class echo $newobj->callProtected(); ?>
Actualisez la page de votre navigateur pour exécuter le script, et vous verrez l'erreur suivante:
The class "MyClass" was initiated! A new constructor in MyOtherClass. Fatal error: Call to private method MyClass::getProperty() from context 'MyOtherClass' in /Applications/XAMPP/xamppfiles/htdocs/testing/test.php on line 49
Les Propriétés et Méthodes statiques
Une méthode ou propriété déclarée static
est accessible sans avoir besoin d'instancier un objet pour la classe; il vous suffit d'utiliser les doubles deux points (::)
"Un des plus gros avantages des propriétés statiques est qu'elles peuvent stocker des valeurs pendant la durée d'exécution du script."
Ajoutez donc une propriété statique appelée $count
et une méthode statique appelée plusOne()
à MyClass
. Puis, ajoutez une boucle do...while
pour incrémenter la valeur de $count
tant qu'il est inférieur à 10:
<?php class MyClass { public $prop1 = "I'm a class property!"; public static $count = 0; public function __construct() { echo 'The class "', __CLASS__, '" was initiated!<br />'; } public function __destruct() { echo 'The class "', __CLASS__, '" was destroyed.<br />'; } public function __toString() { echo "Using the toString method: "; return $this->getProperty(); } public function setProperty($newval) { $this->prop1 = $newval; } private function getProperty() { return $this->prop1 . "<br />"; } public static function plusOne() { return "The count is " . ++self::$count . ".<br />"; } } class MyOtherClass extends MyClass { public function __construct() { parent::__construct(); echo "A new constructor in " . __CLASS__ . ".<br />"; } public function newMethod() { echo "From a new method in " . __CLASS__ . ".<br />"; } public function callProtected() { return $this->getProperty(); } } do { // Call plusOne without instantiating MyClass echo MyClass::plusOne(); } while ( MyClass::$count < 10 ); ?>
Note - Lorsque l'on accède à des propriétés statiques, le dollar
($
)se met après des doubles deux points.
Après rechargement du script dans le navigateur, voici le résultat:
The count is 1. The count is 2. The count is 3. The count is 4. The count is 5. The count is 6. The count is 7. The count is 8. The count is 9. The count is 10.
Commenter avec DocBlocks
"Le style de commentaire DocBlock est une
façon largement répandue de documenter ses classes."
Bien qu'il ne s'agisse pas d'une partie officielle de la POO, le DocBlock est une façon de documenter ses classes largement répandue. En plus de fournir un standard d'écriture pour
les développeurs, il a également été adopté par beaucoup de logiciels de développement populaires (SDKs), comme Eclipse ou NetBeans, et est utilisé pour générer des informations sur le code.
Un DocBlock se crée en commençant un bloc de commentaire, puis en ajoutant une astérisque supplémentaire:
/** * This is a very basic DocBlock */
Le vrai pouvoir des DocBlocks c'est de pouvoir utiliser des tags, qui commencent avec un symbole "at" (@
) immédiatement suivi du nom de tag et de la valeur du tag. Les tags permettent aux développeurs de définir par exemple l'auteur d'un fichier, la licence d'une classe, des informations pour une propriété ou une méthode, etc..
Les tags les plus utilisés:
- @author: l'auteur de l'élément courant(qui peut être une classe, un fichier, une méthode, ou n'importe quel bout de code) Il est possible d'utiliser plusieurs tags auteurs dans le même DocBlock si besoin. Le format pour les noms d'auteur est
John Doe <john.doe@email.com>
. - @copyright: c'est l'année du copyright et le nom du détenteur de ce copyright pour l'élément en cours. Le format est
2010 Copyright Holder
. - @license: Lien vers la licence pour l'élément courant. Le format pour la licence d'information est
http://www.example.com/path/to/license.txt License Name
. - @var: Il contient le type et la description d'une variable ou une propriété de classe. Le format est
type element description
. - @param: Ce tag montre le type et la description d'un paramètre d'une fonction ou d'une méthode. Le format est
type $element_name element description
. - @return: Le type et la description de la valeur retournée d'une fonction ou d'une méthode sont décrites dans ce tag. Le format est
type return element description
.
Un exemple de classe commentée en DocBlocks ressemble à ceci:
<?php /** * A simple class * * This is the long description for this class, * which can span as many lines as needed. It is * not required, whereas the short description is * necessary. * * It can also span multiple paragraphs if the * description merits that much verbiage. * * @author Jason Lengstorf <jason.lengstorf@ennuidesign.com> * @copyright 2010 Ennui Design * @license http://www.php.net/license/3_01.txt PHP License 3.01 */ class SimpleClass { /** * A public variable * * @var string stores data for the class */ public $foo; /** * Sets $foo to a new value upon class instantiation * * @param string $val a value required for the class * @return void */ public function __construct($val) { $this->foo = $val; } /** * Multiplies two integers * * Accepts a pair of integers and returns the * product of the two. * * @param int $bat a number to be multiplied * @param int $baz a number to be multiplied * @return int the product of the two parameters */ public function bar($bat, $baz) { return $bat * $baz; } } ?>
Si vous lisez la classe précédente, les avantages de DocBlock deviennent évidents: tout est clair et défini afin que le prochain développeur puisse comprendre le code sans avoir à se demande quel bout de code fait quoi ou ce qu'il contient.
Comparaison de l'Orienté Objet et du Code Procédural
Il n'y a pas vraiment de bon ou de mauvais moyens pour écrire du code. Ceci étant dit, cette section mettra en lumière les arguments principaux en faveur de la programmation orientée objet dans le développement, en particulier lorsqu'il s'agit de grosses applications.
Raison 1: la facilité d'implémentation
Bien que ça puisse paraître plus compliqué aux premiers abords, la POO facilite largement l'interaction entre les données.
Bien que ça puisse paraître plus compliqué aux premiers abords, la POO facilite largement l'interaction entre les données. Etant donné qu'un objet peut stocker des données en interne, les variables n'ont pas besoin d'être passées de fonction en fonction pour fonctionner correctement.
De même, puisque l'on peut créer plusieurs instances de la même classe, il devient infiniment plus facile de gérer plusieurs sets de données. Par exemple, imaginez que vous avez deux personnes dont vous devez insérer les données dans un fichier. Ils ont besoin de noms, de jobs, et d'âges.
L'approche procédurale
Voici l'approche procédurale de notre exemple:
<?php function changeJob($person, $newjob) { $person['job'] = $newjob; // Change the person's job return $person; } function happyBirthday($person) { ++$person['age']; // Add 1 to the person's age return $person; } $person1 = array( 'name' => 'Tom', 'job' => 'Button-Pusher', 'age' => 34 ); $person2 = array( 'name' => 'John', 'job' => 'Lever-Puller', 'age' => 41 ); // Output the starting values for the people echo "<pre>Person 1: ", print_r($person1, TRUE), "</pre>"; echo "<pre>Person 2: ", print_r($person2, TRUE), "</pre>"; // Tom got a promotion and had a birthday $person1 = changeJob($person1, 'Box-Mover'); $person1 = happyBirthday($person1); // John just had a birthday $person2 = happyBirthday($person2); // Output the new values for the people echo "<pre>Person 1: ", print_r($person1, TRUE), "</pre>"; echo "<pre>Person 2: ", print_r($person2, TRUE), "</pre>"; ?>
A l'exécution, ce code donnera le résultat suivant:
Person 1: Array ( [name] => Tom [job] => Button-Pusher [age] => 34 ) Person 2: Array ( [name] => John [job] => Lever-Puller [age] => 41 ) Person 1: Array ( [name] => Tom [job] => Box-Mover [age] => 35 ) Person 2: Array ( [name] => John [job] => Lever-Puller [age] => 42 )
Même si ce code n'est pas nécessairement mauvais, il y a beaucoup de choses à garder en tête tout en codant. Le tableau avec l'attribut de la personne concernée doit être passée puis retournée à chaque appel de fonction, ce qui augmente le risque d'erreur.
Pour clarifier cet exemple, il serait souhaitable que le développeur aie le moins de choses à faire possible. Il n'y a que les données essentielles pour l'opération en cours qui devraient être passée à la fonction.
C'est là que la POO entre en jeu et vous aide à améliorer les choses.
L'approche POO
Voici donc notre exemple en POO:
<?php class Person { private $_name; private $_job; private $_age; public function __construct($name, $job, $age) { $this->_name = $name; $this->_job = $job; $this->_age = $age; } public function changeJob($newjob) { $this->_job = $newjob; } public function happyBirthday() { ++$this->_age; } } // Create two new people $person1 = new Person("Tom", "Button-Pusher", 34); $person2 = new Person("John", "Lever Puller", 41); // Output their starting point echo "<pre>Person 1: ", print_r($person1, TRUE), "</pre>"; echo "<pre>Person 2: ", print_r($person2, TRUE), "</pre>"; // Give Tom a promotion and a birthday $person1->changeJob("Box-Mover"); $person1->happyBirthday(); // John just gets a year older $person2->happyBirthday(); // Output the ending values echo "<pre>Person 1: ", print_r($person1, TRUE), "</pre>"; echo "<pre>Person 2: ", print_r($person2, TRUE), "</pre>"; ?>
On obtient alors le résultat suivant:
Person 1: Person Object ( [_name:private] => Tom [_job:private] => Button-Pusher [_age:private] => 34 ) Person 2: Person Object ( [_name:private] => John [_job:private] => Lever Puller [_age:private] => 41 ) Person 1: Person Object ( [_name:private] => Tom [_job:private] => Box-Mover [_age:private] => 35 ) Person 2: Person Object ( [_name:private] => John [_job:private] => Lever Puller [_age:private] => 42 )
Il faut un peu plus de préparation pour l'approche en orienté objet, mais une fois que la classe est définie, créer et modifier des personnes est un jeu d'enfant; les données d'une personne n'ont pas besoin d'être passée ou retournée depuis les méthodes, et chaque méthode ne reçoit que les informations dont elle a besoin.
La POO peut réduire significativement votre charge de travail, si elle est utilisée correctement.
A petite échelle, la différence peut ne pas se voir, mais à mesure que votre application grandira, la POO pourra réduire significativement votre charge de travail, si elle est utilisée correctement.
Tip - Tout n'a pas besoin d'être codé en orienté objet. Une petite fonction qui exécute une petite chose à un endroit dans l'application ne doit pas forcément être inclus dans une classe. Jugez en votre âme et conscience de la nécessité d'utiliser la POO ou le procédural selon ce que vous avez comme code devant vous!
Raison 2: Une Meilleure Organisation
Un des autres bénéfices de la POO est la facilité avec laquelle il est possible de tout ranger et cataloguer. Chaque classe peut généralement être stockée dans son propre fichier, à part, et si une convention de nommage uniforme est adoptée, il est extrêmement simple d'accéder aux classes.
Imaginez que vous avez une application avec 150 classes appelées dynamiquement à travers un fichier contrôleur à la racine de votre système de fichier. Les 150 classes suivent la convention de nommage class.classname.inc.php
et résident dans le fichier inc
de votre application.
Le fichier contrôleur peut implémenter la fonction PHP __autoload()
pour inclure dynamiquement seulement les classes lorsqu'elles sont appelées, plutôt que d'inclure les 150 classes d'un coup dans le fichier contrôleur, "au cas où".
<?php function __autoload($class_name) { include_once 'inc/class.' . $class_name . '.inc.php'; } ?>
Le fait de séparer chaque classes dans un fichier à part rend également le code plus "portable" et plus facile à réutiliser dans de nouvelles applications sans avoir à faire un tas de copier-coller.
Raison 3: Une Maintenance Facilitée
Etant donnée la nature plus compacte de la POO lorsqu'elle est fait correctement, les changements dans le code sont souvent plus facile à repérer et à effectuer plutôt que dans un code procédural tout en spaghetti!
En procédural, si un tableau d'information doit contenir un nouvel attribut, il faudrait (dans le pire des cas) ajouter ce nouvel attribut dans chaque fonction qui utiliserait ce tableau.
En POO, l'application pourrait potentiellement être mise à jour très facilement, en ajoutant simplement la nouvelle propriété puis les méthodes liées à cette nouvelle propriété.
La plupart des avantages cités ici sont le produits de la POO combinée au principe de programmation DRY (Don't Repeat Yourself, en français, ne pas se répéter dans son code). Il est tout à fait possible de créer du code procédural facile à maintenir, tout comme il est possible de créer un code orienté objet absolument cauchemardesque. [Pro PHP and jQuery] essaie de parcourir un certain nombre de bonne pratiques de programmation en combinaison avec la POO pour générer un code propre, facile à lire et à maintenir.
Pour résumer
Maintenant, vous devriez vous sentir à l'aise avec la POO. Apprendre la POO est un bon moyen pour améliorer votre niveau de programmation. Utilisé correctement, la POO vous aidera à créer un code facile à lire et à maintenir, et à réutiliser, ce qui pourrait parfois vous éviter (à vous, et aux développeurs qui travaillent avec vous) des heures de travail supplémentaire. Vous êtes bloqués sur un point qui n'était pas décrit dans cet article? Vous utilisez déjà la POO et vous avez des astuces pour les débutants? Partagez tout ça dans les commentaires!
Note de l'auteur : Ce tutoriel est un extrait de PHP et jQuery Pro (Apress, 2010).