Créer une classe en PHP

| Wes Shell (Auteur) | Joris Crozier (Traducteur) |

Cet article est la traduction de Class Design in PHP de Wes Shell, il parle des bonnes pratiques de la POO en PHP.

Commentez

- Titre : Créer une classe en PHP

- Auteurs : Wes Shell (Auteur), Joris Crozier (Traducteur)

- Parution : 28 octobre 2009

- Mise à jour : 10 décembre 2019

- Licence : Copyright ® 2009 Joris CROZIER. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Introduction

- II. Exercice

- III. Continuons

- IV. Liens

I - Introduction

Les classes sont le cœur de la programmation objet en PHP. L'idée générale derrière la POO est de regrouper les fonctions similaires au sein d'objets. Ces objets représentent des choses réelles comme des gens, des lieux ou des choses. D'une certaine manière, si un programme était une phrase, tous les noms de cette phrase seraient des objets.

Ex. : Chat dans le Chapeau

Dans cet exemple, nous avons deux objets, Chat et Chapeau. Dans le but de construire une représentation de ces objets, nous allons utiliser le mot clef class en PHP.

class Chat { }

class Chapeau { }

Ces classes sont utilisées pour décrire nos objets. Le mot qui suit le mot clef class décrit un genre d'objets que la classe représente. Nos classes représentent un Chat et un Chapeau. Pour créer nos objets, nous utilisons la syntaxe suivante :

$monChat = new Chat();

Regardez le mot clef new. Cela précise à PHP que nous voulons créer un nouvel objet de type Chat. Les parenthèses sont requises et invoquent le constructeur de la classe. Le constructeur est le code qui est exécuté quand la classe crée un nouvel objet. Nous parlerons de la construction plus loin dans cet article.

Techniquement ce code a créé un objet de type Chat. Cependant notre classe Chat est vraiment basique et ne contient pas d'information ou d'action utiles. Dans le but de mieux décrire notre Chat nous devons lui donner quelques propriétés. Les propriétés décrivent un objet comme les adjectifs décrivent un nom.

class Chat
{
var $_couleur;
var $_race;
}

Note : la bonne pratique fait nommer nos champs avec le préfixe _. Cela nous permet de vite nous faire savoir que cette variable représente un champ de notre classe. Vous avez sûrement dû voir des gens utiliser les préfixes m_ et c_ pour représenter un 'membre' ou un 'champ'.

OK donc nous avons quelques champs pour stocker les informations qui décrivent notre chat. Maintenant nous devons protéger ces champs pour limiter la façon dont ils peuvent être accédés. Ces champs sont comme notre ADN et sont très importants donc il est toujours de bon usage de contrôler la manière d'y accéder.

Pour ce faire nous allons utiliser les mots clefs 'public', 'private' et 'protected'. Par défaut tous les champs sont 'public', ce qui veut dire qu'ils peuvent être accessibles depuis la classe ou depuis l'extérieur de celle-ci. Ce peut être très mauvais, car cela autorise vos champs à être manipulés par n'importe qui. Cela tend à causer des erreurs de runtime inattendues.

'Protected' veut dire que les champs peuvent seulement être accessibles par les fonctions de la classe ou celles des classes qui étendent celle-ci. Comme cet article ne traite pas de l'héritage et de l'extension de classe, nous ne parlerons pas de cette option.

'Private' est l'option la plus sécurisée. Cela veut dire que les champs peuvent seulement être accessibles par les fonctions de la classe. C'est bien, car vous pouvez contrôler quand et comment les informations peuvent être modifiées ou accédées. Normalement c'est la meilleure option à choisir pour les champs d'une classe et nous allons l'utiliser pour notre classe Chat.

class Chat
{
private $_couleur;
private $_race;
}

Maintenant nous avons besoin d'une méthode d'accès pour entrer des valeurs dans ces champs. Comme elles sont en 'private' nous ne pouvons pas les configurer depuis l'extérieur de notre objet. Ce qui veut dire que le code suivant provoquera une exception :

$monChat = new Chat();
$monChat->_couleur = "Vert";

Donc comment allons-nous entrer des valeurs dans ces champs. Dans notre cas la couleur est 'vert' et la race est 'calico'. Pour ce faire, nous allons utiliser notre constructeur de classe. Comme décrit plus bas, le constructeur de classe est un bloc de code qui est exécuté quand la classe est instanciée ou en utilisant le mot clef new.

Par défaut le constructeur est appelé pour créer une représentation de l'objet. Ce code est une part du langage PHP et est exécuté chaque fois qu'une classe est instanciée. Instancier veut dire qu'une instance de la classe est créée sous la forme d'un objet. On peut ajouter des instructions spéciales à ce code en utilisant notre propre méthode _construct qui sera exécutée juste après le constructeur par défaut.

class Chat
{
private $_couleur;
private $_race;

function __construct()
{
$this->_couleur = "Vert";
$this->_race = "Calico";
}
}

Au regard du code précédent, vous devriez être en mesure de savoir ce qui se passe ici. La seule chose qui peut différer est l'utilisation du mot clef 'this'. Cette variable spéciale est une référence aux champs de l'objet. En gros nous configurons 'this' couleur du chat et 'this' race du chat. Maintenant chaque fois que le constructeur sera exécuté les champs du chat seront configurés pour décrire celui-ci.

OK, c'est génial, mais que faire si nous ne voulons pas que des chats calico verts. Nous voudrions plusieurs chats différents. La réponse est facile. Comme n'importe quelle autre fonction, la fonction _construct peut recevoir des valeurs en paramètres. Pour permettre une manière de décrire le chat au créateur de l'objet, nous allons passer une variable pour la couleur et pour la race. Ensuite nous utiliserons ces valeurs pour renseigner les champs de la classe Chat.

class Chat
{
private $_couleur;
private $_race;

function __construct($couleur, $race)
{
$this->_couleur = $couleur;
$this->_race = $race;
}
}
$monChat = new Chat("Vert","Calico");

Maintenant nous avons une méthode pour décrire les champs de notre chat, nous voulons une manière de les récupérer pour que d'autres parties du programme puissent utiliser ces informations. Pour ce faire nous utilisons des fonctions publiques au sein de la classe pour retourner les valeurs désirées. Il y a beaucoup de méthodes pour faire ceci et je vous encourage à toutes les étudier. La technique que j'utilise simule le mieux la manière dont les propriétés marchent en C#, un langage fortement typé.

Tout d'abord, nous devons déclarer une fonction pour tous les champs auxquels nous voulons accéder. Le nom de la fonction doit décrire le champ auquel elle accède.

public function Couleur()
{
return $this->_couleur;
}

public function Race()
{
return $this->_race;
}

Quand ces méthodes sont appelées par nos objets, elles vont retourner les valeurs stockées dans nos champs privés sécurisés. Maintenant nous pouvons partager la description de notre chat avec le reste du monde.

$monChat = new Chat("vert","calico");
echo "Le chat " . $monChat->Couleur() . " " . $monChat->Race() . " peut s'asseoir sur le grand chapeau rayé.";

//Affiche: Le chat vert calico peut s'asseoir sur le grand chapeau rayé.

Nous pouvons maintenant créer un chat avec une belle description et partager ces détails avec les autres. Mais si nous voulons changer la description de ce chat. Nous pouvons utiliser les mêmes propriétés pour autoriser l'utilisateur à changer ces valeurs. Le code pour le faire est présenté ci-dessous, je vais expliquer ce qu'il se passe en m'appuyant sur cet exemple :

public function Couleur($value = "")
{
if ($value == "")
{
return $this->_couleur;
}

$this->_couleur = $value;
}

public function Race($value = "")
{
if ($value == "")
{
return $this->_race;
}

$this->_race = $value;
}

Regardez la partie du code que nous avons modifiée en commençant par le nom de la fonction. Nous avons ajouté un attribut '$value' avec une valeur par défaut vide. Cela veut dire que si la fonction est appelée sans paramètre, la valeur par défaut sera une chaîne vide.

Ensuite regardez le block if que nous avons ajouté. Précédemment nous retournions la valeur de nos champs chaque fois que la propriété était appelée. Maintenant nous voulons retourner la valeur seulement si aucune valeur n'est transmise à la propriété. La commande if vérifie si $value est une chaîne vide. Si elle l'est, la propriété retourne la valeur actuelle du champ.

Si la valeur passée n'est pas vide, nous savons que nous devons changer la valeur actuelle du champ par celle envoyée à la méthode. On procède de la même manière que dans le constructeur en utilisant le mot clef 'this'. Maintenant si nous voulons changer des propriétés du chat nous pouvons le faire depuis l'extérieur de la classe.

$monChat = new Chat("vert","calico");

echo "Le chat " . $monChat->Couleur() . " " . $monChat->Race() . " est assis sur le grand chapeau rayé.";

//Affiche: Le chat vert calico peut s'asseoir sur le grand chapeau rayé.

$monChat = new Chat("violet","calico");

echo "Le chat " . $monChat->Couleur() . " " . $monChat->Race() . " est assis sur le grand chapeau rayé.";

//Affiche: Le chat violet calico peut s'asseoir sur le grand chapeau rayé.

II - Exercice

Maintenant regardez si vous pouvez mettre en application ce que vous avez appris en essayant de compléter la classe Chapeau. Pour vous aider à commencer, je vais vous donner le nom des champs à utiliser dans votre classe.

$_modele, $_taille

Le code complet :

class Chat
{
private $_couleur;
private $_race;

function __construct($couleur, $race)
{
$this->_ couleur = $couleur;
$this->_race = $race;
}

public function Couleur($value = "")
{
if ($value == "")
{
return $this->_couleur;
}

$this->_couleur = $value;
}

public function Race($value = "")
{
if ($value == "")
{
return $this->_race;
}

$this->_race = $value;
}
}

class Chapeau
{
private $_modele;
private $_taille;

function __construct($modele, $taille)
{
$this->_modele = $modele;
$this->_taille = $taille;
}

public function Modele($value = "")
{
if ($value == "")
{
return $this->_modele;
}

$this->_modele  = $value;
}

public function Taille($value = "")
{
if ($value == "")
{
return $this->_taille;
}

$this->_taille = $value;
}
}

III - Continuons

Maintenant que nous avons nos objets Chat et Chapeau et leurs propriétés respectives, nous pouvons les utiliser pour compléter la phrase.

$monChat = new Chat("vert","calico");
$monChapeau = new Chapeau("rayé","grand");

echo "Le chat " . $monChat->Couleur() . " " . $monChat->race() . " est assis sur le "
. $monChapeau ->Taille() . " chapeau " . $monChapeau ->Modele() . ".";

//Affiche: Le chat vert calico est assis sur le grand chapeau rayé.

Donc vous vous dites que c'est génial, mais pourquoi faire tout ce travail alors que l'on pourrait le faire avec un tableau associatif. Évidemment il y a des bénéfices à utiliser des classes sinon cette option n'existerait pas. Pour en savoir plus sur l'application de la POO en PHP veuillez lire l'article sur la POO en PHP. https://jcrozier.developpez.com/tutoriels/web/php/programmation-orientee-objet/

Une des forces des classes est leur capacité d'exécuter des actions aussi bien que tenir des informations descriptives. Les actions qu'elles exécutent sont comme des verbes dans une phrase.

Ex. : Le chat vert calico est assis sur le grand chapeau rayé.

Notre chat doit avoir la capacité de s'asseoir avant de pouvoir s'asseoir sur notre chapeau. Pour faire ceci, nous allons créer une fonction dans notre classe pour exécuter cette action.

public function Asseoir() {  }

Ensuite nous allons avoir besoin d'un champ supplémentaire pour savoir sur quoi le chat est assis. C'est une bonne pratique de garder tous nos champs déclarés au même endroit au début de la description de l'objet afin qu'ils soient facilement repérables plus tard. Retournons donc au début de notre classe Chat, nous allons ajouter un nouveau champ appelé $_assis.

class Chat
{
private $_couleur;
private $_race;
private $_assis;    // Objet

...
}

Note : les caractères … dans l'exemple ci-dessus indiquent la suite du code que nous avons déjà décrite précédemment.

Une autre bonne pratique est de commenter le champ qui stocke les références vers d'autres objets comme ça vous et les autres savez à quoi va servir le champ sans avoir à parcourir tout le code. Maintenant que nous avons une fonction Asseoir() et une place pour stocker sur quoi le chat est assis, nous pouvons compléter notre fonction. Tout d'abord, nous allons ajouter un paramètre à la fonction pour pouvoir passer sur quoi le chat va s'asseoir.

public function Asseoir($assis)
{
$this->_assis = $assis;
}

La fonction précédente s'explique d'elle-même. Quand elle est appelée, un objet 'assis' va être passé et le champ $_assis va être configuré avec la référence de l'objet $assis. La fonction va marcher dans l'état, mais il y aura un petit problème. À cet instant nous sommes capables de configurer la valeur du champ $_assis sans que ce soit un objet. Notre commentaire indique que nous attendons une référence à un objet et non à une chaîne de caractères. Comme indiqué précédemment quand on parle d'une propriété, nous pouvons contrôler comment notre champ est configuré. Pour ce faire nous devons juste ajouter un peu de code à notre fonction.

public function Asseoir($assis)
{
if (!is_object($assis))
{
throw new Exception("Assis n'est pas un objet dans la fonction Asseoir().");
}

$this->_assis  = $assis;
}

Maintenant si l'utilisateur de notre objet de classe essaie d'asseoir le chat sur quelque chose qui n'est pas un objet, une exception sera levée stipulant qu'il ne peut pas faire ça. La dernière chose qu'il reste à faire est de fournir une manière à l'application d'en savoir plus sur quoi notre chat est assis. Pour ça nous devons créer une propriété pour notre assise. Comme nous voulons que l'utilisateur puisse seulement configurer la valeur du siège en utilisant la propriété Asseoir(), la propriété que nous allons créer ne permettra pas de changer cette valeur.

public function Siege()
{
return $this->_assis;
}

En combinant tout ceci, notre classe finale devrait ressembler à ça :

class Chat
{
private $_couleur;
private $_race;
private $_assis; // Objet

function __construct($couleur, $race)
{
$this->_ couleur = $couleur;
$this->_race = $race;
}

public function Couleur($value = "")
{
if ($value == "")
{
return $this->_couleur;
}

$this->_couleur = $value;
}

public function Race($value = "")
{
if ($value == "")
{
return $this->_race;
}

$this->_race = $value;
}

public function Siege()
{
return $this->_assis;
}

public function Asseoir($assis)
{
if (!is_object($assis))
{
throw new Exception("Assis n'est pas un objet dans la fonction Asseoir().");
}

$this->_assis = $assis;
}
}

Maintenant notre chat possède une manière de s'asseoir sur un objet et de faire savoir aux autres les propriétés le sur quoi il est assis. En revenant à notre phrase originale, nous pouvons maintenant remplacer tous les noms, les adjectifs et les verbes avec les informations de notre objet.

$monChat = new Chat("vert","calico");
$monChapeau = new Chapeau("rayé","grand");

$monChat ->Asseoir($monChapeau);

$monSiege = $monChat ->Siege();

echo "Le " . get_class($monChat). "  " . $monChat ->Couleur() . " " . $monChat ->Race .
" est assis sur  un" . $monSiege ->Taille() . " ". get_class($monSiege) . " ". $monSiege ->Modele() ;

//Affiche: Le chat vert calico est assis sur un grand chapeau rayé.

La fonction get_class() est une fonction native de PHP qui retourne le nom de la classe responsable de la création de l'objet. Dans notre cas l'objet $monChat a été créé par la classe Chat et l'objet $monSiege a été créé par la classe Chapeau.

Bien que ce soit une application peu probable, le but est de vous montrer comment créer vos propres objets de classe. Pour plus d'exemples de classes, d'objets et sur la manière d'utiliser les objets, veuillez lire l'article sur la POO en PHP.

class Chat
{
private $_couleur;
private $_race;
private $_assis; // Objet

function __construct($couleur, $race)
{
$this->_ couleur = $couleur;
$this->_race = $race;
}

public function Couleur($value = "")
{
if ($value == "")
{
return $this->_couleur;
}

$this->_couleur = $value;
}

public function Race($value = "")
{
if ($value == "")
{
return $this->_race;
}

$this->_race = $value;
}

public function Siege()
{
return $this->_assis;
}

public function Asseoir($assis)
{
if (!is_object($assis))
{
throw new Exception("Assis n'est pas un objet dans la fonction Asseoir().");
}

$this->_assis = $assis;
}
}

class Chapeau
{
private $_modele;
private $_taille;

function __construct($podele, $taille)
{
$this->_modele = $modele;
$this->_taille = $taille;
}

public function Modele($value = "")
{
if ($value == "")
{
return $this->_modele;
}

$this->_modele  = $value;
}

public function Taille($value = "")
{
if ($value == "")
{
return $this->_taille;
}

$this->_taille = $value;
}
}

$monChat = new Chat("vert","calico");
$monChapeau = new Chapeau("rayé","grand");

$monChat ->Asseoir($monChapeau);

$monSiege = $monChat ->Siege();

echo "Le " . get_class($monChat). "  " . $monChat ->Couleur() . " " . $monChat ->Race .
" est assis sur  un" . $monSiege ->Taille() . " " . get_class($monSiege) . " ". $monSiege ->Modele() ;

//Affiche: Le chat vert calico est assis sur un grand chapeau rayé.

IV - Liens

Vous pouvez aussi aller voir mes autres traductions.