Presentation de la POO (programmation orientee objet) en PHP

La POO (programmation orientee objet) est une forme particuliere de programmation destinee a faciliter la maintenance et la reutilisation / adaptation de vos scripts PHP. Elle consiste a representer des objets (du monde reel ou non) sous une forme d'entites informatiques. On represente generalement un objet global par ce que l'on appelle une classe. Une classe va regrouper un ensemble de fonctions et de proprietes pouvant agir sur l'objet. Si on prend par exemple une voiture dans le monde reel, on peut modeliser une voiture par une classe "Voiture" qui aura comme proprietes le nombre de roues, le nombre de portes, etc ...

Les classes

Une classe regroupe des fonctions et des variables (appelees cette fois "attributs", car il s'agit des attributs d'une classe) qui interragissent avec l'objet. C'est a dire que pour un objet "voiture" par exemple, vous aurez une classe nommee "Voiture" et vous pourrez avoir une fonction qui modifie le niveau de carburant (le niveau de carburant etant un attribut de la classe que l'on ne peut modifier que via une fonction (appelee "methode") qui ira modifier cet attribut). On appelle ce principe l'encapsulation des donnees, le but de l'encapsulation des donnees etant de ne pas pouvoir acceder aux donnees de l'objet directement mais via des fonctions (appelees ici "methodes"). Chaque attribut peut donc disposer de droits d'acces a l'exterieur de la classe. Nous verrons tout ceci au fur et a mesure que vous lisez cette page.

Avant toute chose, PHP 5 a ameliore le support objet de PHP par rapport a PHP 4, nous allons donc utiliser PHP 5 pour tous nos exemples. Si vous avez besoin de savoir comment PHP 4 fonctionne avec l'objet, je vous conseille d'aller jeter un oeil dans la rubrique codes sources orientes objet du site, qui vous permettra d'obtenir des sources de tous types.

Voici comment une classe peut etre codee en PHP 5 :

<?php
     
class Voiture
     
{
          
/**
          * Declaration des attributs
          */

          
private $niveau_carburant;
          private 
$nombre_portes;
          private 
$nombre_roues;

          
/**
          * Cette methode un peu speciale est le constructeur, elle est executee lorsque vous "creez" votre objet. Elle doit initialiser les attributs de la classe.
          */

          
public function __construct()
          {
               
$this->niveau_carburant 50;
               
$this->nombre_portes 3;
               
$this->nombre_roues 4;
          }

          
/**
          * Premiere methode accessible par tous et modifiant le niveau de carburant
          */

          
public function modifier_carburant(int $niveau)
          {
               
$this->niveau_carburant $niveau;
          }

          /**
          * Seconde methode accessible a tous et modifiant le nombre de portes
          */

         
public function modifier_nb_portes(int $nb_portes)
          {
               
$this->nombre_portes = $nb_portes;
          } 

     }
?>
Notion d'objet

Imaginions que vous souhaitiez creer deux voitures dans votre code. Sans programmation orientee objet, on aurait pu stocker les voitures et leurs attributs dans un tableau, ce qui devient vite impossible a gerer. Avec la programmation orientee objet, vous allez pouvoir creer deux objets differents en deux lignes de code. Creer un objet se fait en "instanciant" une classe. Quand on instancie une classe, on cree une version de l'objet ayant des caracteristiques propres. Si vous creez un deuxieme objet, il est independant du premier, bien qu'ils utilisent tous les deux la meme classe (ici nos deux objets seront des voitures, ils utiliseront donc la meme classe "Voiture", mais seront bien differents pour autant. Nous pourrons par exemple avoir une voiture ayant trois portes et la seconde 5 portes).

Creer un objet (instanciation d'une classe)

Voici comment on cree un objet Voiture en PHP (on supposera que vous avez inclus le fichier contenant la classe, ou alors que le code de la classe se trouve au dessus du code que vous allez voir) :

<?php
     $objet_voiture 
= new Voiture();
?>

La variable $objet_voiture represente l'objet qui est ici une voiture. Lorsque vous executez ce code, la methode __construct() de la classe est executee. Comme il s'agit d'une fonction, elle peut prendre elle aussi des parametres. Tout depend comment vous souhaitez coder votre classe, mais vous pourriez tres bien avoir une fonction __construct() qui initialise les attributs en fonction des parametres que vous lui fournissez. Voici ce que ca pourrait donner :

<?php 
     
class Voiture 
     

          
/** 
          * Declaration des attributs 
          */ 

          
private $niveau_carburant
          private 
$nombre_portes
          private 
$nombre_roues

          
/** 
          * Cette methode un peu speciale est le constructeur, elle est executee lorsque vous "creez" votre objet. Elle doit initialiser les attributs de la classe.
          */ 

          
public function __construct(int $nb_carburantint $nb_portesint $nb_roues 4
          { 
               
$this->niveau_carburant $nb_carburant
               
$this->nombre_portes $nb_portes
               
$this->nombre_roues $nb_roues
          } 

          
/** 
          * Premiere methode accessible par tous et modifiant le niveau de carburant 
          */ 

          
public function modifier_carburant(int $niveau
          { 
               
$this->niveau_carburant $niveau
          }

          
/** 
          * Seconde methode accessible a tous et modifiant le nombre de portes
          */ 

          
public function modifier_nb_portes(int $nb_portes
          { 
               
$this->nombre_portes $nb_portes
          } 
     } 
?>

Lorsque vous creerez l'objet voiture, vous allez pouvoir sans passer par les methodes appropriees lui fixer un niveau de carburant, un nombre de portes et un nombre de roues (par defaut 4). Voici deux facons de creer l'objet :

<?php 
     $objet_voiture 
= new Voiture(503); //50 : niveau de carburant et 3 portes, on a pas besoin de specifier le nombre de roues car il est de 4 par defaut

     
$autre_voiture = new Voiture(1056); //10 : niveau de carburant, 5 portes et 6 roues
?>

Il est important de signifier que les objets $objet_voiture et $autre_voiture sont deux objets differents qui peuvent avoir leurs proprietes propres. Vous commencez peut-etre maintenant a comprendre avec quelle simplicite vous allez pouvoir creer autant d'objets que vous le souhaitez ;)

Constructeurs et destructeurs

Les constructeurs et destructeurs sont des methodes particulieres. D'une part, elle commencent par deux signes "underscores" accoles (touche 8 du pave alphanumerique). D'autre part, elles sont executees a des moments precis.

Le constructeur est appele automatiquement quand vous creez votre objet. Generalement, cette methode sert a donner une valeur de depart aux differents attributs de la classe pour vous permettre de "construire" l'objet. Ce n'est cependant pas une obligation et vous pouvez tres bien ne rien mettre dans cette methode.

Le destructeur est appele a la fin d'execution de votre script. La methode s'appelle cette fois-ci __destruct().

<?php 
     
class Voiture 
     

          
/** 
          * Declaration des attributs 
          */ 

          
private $niveau_carburant
          private 
$nombre_portes
          private 
$nombre_roues

          
/** 
          * Cette methode un peu speciale est le constructeur, elle est executee lorsque vous "creez" votre objet. Elle doit initialiser les attributs de la classe.
          */ 

          
public function __construct(int $nb_carburantint $nb_portesint $nb_roues 4
          { 
               
$this->niveau_carburant $nb_carburant
               
$this->nombre_portes $nb_portes
               
$this->nombre_roues $nb_roues
          }  

          /** 
          * Destructeur, appele quand l'objet est detruit
          */ 

         
public function __destruct(
          {  
               echo 'L\'objet a ete detruit';
          }
     }
?>
Visibilite des proprietes et methodes

PHP 5 introduit la notion de visibilite de methodes et d'attributs. Chaques attributs et methodes peuvent se voir attribuer un droit d'acces. Le principe de l'encapsulation voudrait que l'on mette tous les attributs uniquement modifiables et accessibles a l'interieur de la classe, et les methodes accessibles de l'exterieur. En pratique, ce n'est pas toujours le cas.

Les trois mots permettant de gerer les acces sont ceux-ci :

Pour la classe Voiture, vous pouvez constater que les attributs ne sont pas modifiables a l'exterieur de la classe, il faut passer par les methodes appropriees.

Pour acceder a un attribut d'une classe, on utilise ce code : $objet->attribut

<?php  
     
class Voiture  
     
{  
          
/**  
          * Declaration des attributs  
          */  

          
private $niveau_carburant;  
          public 
$nombre_portes;  
          private 
$nombre_roues;

          
/**  
          * Cette methode un peu speciale est le constructeur, elle est executee lorsque vous "creez" votre objet. Elle doit initialiser les attributs de la classe. 
          */  

          
public function __construct(int $nb_carburantint $nb_portesint $nb_roues 4)  
          {  
               
$this->niveau_carburant $nb_carburant;  
               
$this->nombre_portes $nb_portes;  
               
$this->nombre_roues $nb_roues;  
          }
     }
?>

Maintenant, on instancie la classe :

<?php
     $voiture 
= new Voiture(503);

     echo 
$voiture->nombre_portes//va afficher "3" car l'attribut est en acces public

     
echo $voiture->nombre_roues//Erreur, on ne peut pas y acceder car l'attribut est en acces prive !
?>

Notez que l'on ne met pas de signe $ pour acceder ou definir des valeurs aux attributs d'une classe. Le mot-cle $this est un peu special et il designe la classe courante.

L'heritage

L'heritage consiste a utiliser une classe parente et une ou plusieurs classes filles qui heritent des proprietes de la classe parente. Par exemple, si vous avez une classe Vehicule, vous pouvez avoir une classe Voiture qui herite de certaines proprietes de la classe Vehicule, ainsi qu'une autre classe Moto qui va heriter de certaines proprietes de la classe Voiture tout en ajoutant des proprietes propres. Le mot utilise pour dire a PHP qu'une classe herite d'une autre est le mot-cle extends. Prenons l'exemple d'une classe Vehicule :

<?php   
     
class Vehicule
     
{   
          
/**   
          * Declaration des attributs   
          */   

          
protected $prix//On souhaite que les classes qui en heritent puissent y acceder   

          /**   
          * Cette methode un peu speciale est le constructeur, elle est executee lorsque vous "creez" votre objet. Elle doit initialiser les attributs de la classe.  
          */   

          
public function __construct(int $prix_vehicule)   
          {   
               
$this->prix $prix_vehicule;   
          }

          /**   
          * Cette methode permet de modifier le prix du vehicule
         
*/   

          public function modifier_prix;(int $nouveau_prix)   
          {   
               
$this->prix = $nouveau_prix;   
          }
 
     } 
?>

Comme vous pouvez le constater, on a mis dans la classe Vehicule tout ce qui sera commun aux differents vehicules que nous allons pouvoir creer. Ici, j'ai mis un attribut "prix" car une voiture ou une moto ont toutes les deux un prix. On met donc tout ce que les vehicules ont en commun dans une meme classe, et cette classe sera etendue par d'autres classes plus specifiques. Voici maintenant une classe Voiture qui etend les proprietes de la classe Vehicule :

<?php    
     
class Voiture extends Vehicule
     
{    
          
/**    
          * Declaration des attributs    
          */    

          
private $climatisation;

          
/**    
          * Constructeur de la classe Voiture
          */    

          
public function __construct(int $prix_vehiculebool $clim)    
          {
               
parent::__construct($prix_vehicule); //On appelle le constructeur de la classe Vehicule en lui fournissant le prix
               
$this->climatisation $clim;
          }  
     }  
?>

Voici ce que ca donne au niveau de l'instanciation :

<?php 
     $voiture 
= new Voiture(17000TRUE); //On cree une voiture valant 17000 euros et ayant la climatisation

     
$voiture->modifier_prix(15000); //On peut modifier le prix de la voiture
?>

Comme vous pouvez le constater, on peut acceder a la classe parente comme si on accedait a la classe Voiture (avec la methode modifier_prix()). Si vous aviez mis la methode modifier_prix() en acces prive, vous n'auriez pu effectuer la modification directement. Le niveau de protection le plus restrictif permettant cette modification est le niveau protected.

Ceci marque la fin du cours sur ce chapitre, qui est vraiment tres loin d'etre exhaustif. Je vous conseille d'aller lire la documentation de php.net pour avoir plus de precisions sur ce sujet qui meriterait bien plus qu'un chapitre.

Chapitre suivant

Bases de donnees et PHPMyAdmin