Forum de la C-P-F

Version complète: Classes et objets en PHP
Vous regardez actuellement la version basse qualité d'un document. Voir la version complète avec le bon formatage.
De plus en plus, on entend parler de POO (Programmation Orientée Objet).
Les habitués de java (entre autres) connaissent ça par coeur, mais c'est un concept qui n'a atteint sa maturité en PHP que depuis l'avènement de PHP5.

Tout d'abord, qu'est-ce qu'un objet?
C'est tout simplement un élément qui se définit par des propriétés et des méthodes et qui est utilisable à plusieurs moments.

Prenons l'exemple d'une porte, qui est un objet courant. On peut lui définir des propriétés qui seront son état (ouverte, fermée, verouillée) et la pièce (ce qui la rend unique). On peut aussi lui définir des méthodes qui seront ouvrir, fermer, verrouiller, déverouiller.
Vous voyez donc comment l'objet porte peut être appelé plusieurs fois au même moment: si vous définissez votre maison, vous aurez porte(entrée), porte(cuisine), ...

Un objet contient 2 méthodes par défaut (en PHP5), c'est ce qu'on appelle le constructeur et le destructeur.
Le constructeur permet d'initialiser l'objet, donc de lui donner ses paramêtres initiaux. En PHP4, le constructeur se fait en créant dans l'objet une fonction dont le nom est celui de l'objet, alors qu'en PHP5 il y a une fonction __construct()
Le destructeur sert à supprimer cet objet, il n'existe réellement qu'en PHP5.

Pour l'instant, nous nous limiterons à l'utilisation en PHP4.

Comment définir notre porte?
Nous allons créer une classe (qui est donc la définition de l'objet) en lui donnant des paramètres par défaut.
Code PHP :
class porte {
   // par defaut, une porte est fermee, nous initialisons donc son etat par défaut
   var $etat = "fermee";

   function porte($nom,$etat='') {
      // le constructeur: une porte est obligatoirement definie par son nom
      // l'etat initial de la porte peut etre defini
      $this->nom = $nom;
      if ($etat != '') {
         $this->etat = $etat;
      }
   }
}

nous avons donc créé un objet porte qui n'a pas de méthode et qui a 2 propriétés: son nom et son état initial.
Nous allons rajouter les 4 méthodes en tenant compte de certains impératifs:
- une porte ne peut être ouverte que si elle est déverouillée mais fermée,
- une porte ne peut être fermée que si elle est ouverte,
- une porte ne peut être verouillée que si elle est fermée,
- une porte ne peut être déverouillée que si elle est verouillée.
Code PHP :
class porte {
   var $etat = "fermee";

   function porte($nom,$etat='') {
      $this->nom = $nom;
      if ($etat != '') {
         $this->etat = $etat;
      }
   }

   function ouvrir() {
      if ($this->etat == "fermee") {
         $this->etat = "ouverte";
      }
   }

   function fermer() {
      if ($this->etat == "ouverte") {
         $this->etat = "fermee";
      }
   }

   function verouille() {
      if ($this->etat == "fermee") {
         $this->etat = "verouillee";
      }
   }

   function deverouille() {
      if ($this->etat == "verouillee") {
         $this->etat = "deverouillee";
      }
   }
}

nous avons donc nos 4 méthodes et chacune tient compte de l'état précédent de la porte.
nous pouvons tester notre objet...
Code PHP :
// on declare la nouvelle porte, dans son etat par defaut
$entree = new porte("entree_principale");
// on verifie l'etat
echo $entree->etat."<br />";
// on ouvre la porte
$entree->ouvre();
// on verifie l'etat
echo $entree->etat."<br />";
// on essaye de verouiller la porte ouverte
$entree->verouille();
// on verifie l'etat
echo $entree->etat;
 

Nous devrions avoir comme affichage:

Citation :
fermee
ouverte
ouverte

Ainsi, vous venez de voir comment on crée un modèle d'objet, comment on appelle de manière simple une méthode et comment on peut utiliser les propriétés.
La prochaine étape fera intervenir deux points très importants:
- passer des paramètres à une méthode,
- hériter un objet.

Salut,

impec merci !

Ca fait 3 semaines que je fait php et je n'ai pas toucher cette notion de POO.Mais grace a ce tutoriel,j'ai fait une bonne idee,j'attend la 2 eme partie! Big Grin
Et bien voici la deuxième partie...

Tout d'abord, résumons vite la partie précédente:
  • Un objet se crée en faisant une classe
  • Les méthodes sont des fonctions de cette classe
  • Les propriétés sont des variables de cette classe
Vous aurez remarqué que l'on fait les appels internes avec le mot-clé "this" qui représente la classe (l'objet) courant.

Attaquons nous maintenant à l'héritage. Cette notion permet en fait d'étendre l'objet pour lui ajouter des propriétés et des méthodes. Par exemple, nous allons partir de notre porte "basique" et l'adapter à notre maison.
Code PHP :
class porte_modifiee extends porte {
   var $couleur = "bois";

   function porte_modifie($nom, $etat='', $couleur='') {
      $this->nom = $nom;
      if ($etat != '') {
         $this->etat = $etat;
      }
      if ($couleur != '') $this->couleur = $couleur;
   }
}

le premier point important est le mot-clé extends qui permet de définir l'héritage: porte_modifiee etend l'objet porte, cela veut donc dire que toutes les propriétés de l'objet porte font partie de l'objet porte_modifiee.
le second point important concerne le constructeur: nous n'appelons pas le constructeur de l'objet initial, il faut donc que le constructeur de l'objet étendu gère les paramètres par défaut.

Maintenant, nous allons créer une fonction pour repeindre la porte, donc pour modifier la couleur. elle est très simple:
Code PHP :
class porte_modifiee extends porte {
   var $couleur = "bois";

   function porte_modifie($nom, $etat='', $couleur='') {
      $this->nom = $nom;
      if ($etat != '') {
         $this->etat = $etat;
      }
      if ($couleur != '') $this->couleur = $couleur;
   }

   function repeindre($couleur) {
      if ($this->etat == 'ouverte') {
         $this->couleur = $couleur;
      } else {
         return "vous ne pouvez pas peindre une porte fermee";
      }
   }
}

vous constatez que depuis l'objet étendu, on peut atteindre une propriété de l'objet initial sans le moindre soucis, ce qui est logique.

attention: la déclaration des valeurs initiales telle que je l'ai faite dans les exemples n'est pas réellement juste, même si elle fonctionne.
Il vaut mieux simplement initialiser le type de variables et utiliser le constructeur pour affecter les valeurs par défaut.
Voici ce que donne notre code final et propre:
Code PHP :
<?
class porte {
    var $etat;
   
    function porte($nom,$etat='') {
        $this->nom = $nom;
        if ($etat != '') {
            $this->etat = $etat;
        } else {
            $this->etat = 'fermee';
        }
    }
   
    function ouvrir() {
        if ($this->etat == "fermee") {
            $this->etat = "ouverte";
        }
    }
   
    function fermer() {
        if ($this->etat == "ouverte") {
            $this->etat = "fermee";
        }
    }
   
    function verouille() {
        if ($this->etat == "fermee") {
            $this->etat = "verouillee";
        }
    }
   
    function deverouille() {
        if ($this->etat == "verouillee") {
            $this->etat = "deverouillee";
        }
    }
}

class porte_modifiee extends porte {
    var $couleur;

    function porte_modifiee($nom, $etat='', $couleur='') {
        $this->nom = $nom;
        if ($etat != '') {
            $this->etat = $etat;
        } else {
            $this->etat = 'fermee';
        }
        if ($couleur != '') {
            $this->couleur = $couleur;
        } else {
            $this->couleur = 'bois';
        }
    }

    function repeindre($couleur) {
        if ($this->etat == 'ouverte') {
            $this->couleur = $couleur;
        } else {
            return "vous ne pouvez pas peindre une porte fermee";
        }
    }
}

$maporte = new porte_modifiee("principale", "", "bleue");
echo $maporte->nom." -- ".$maporte->etat." -- ".$maporte->couleur;
?>
Salut j'ai une une question :-[,

On regardant certains scripts je vois bcq l'operateur & quand on creer des objets,

Code PHP :
$objet=& new classquelconque();


Je sais que ca veut dire partager le contenu mais la quel es le contenu les valeurs de constructeur ?

Merci !
Il s'agit de ce que l'on appelle le passage par référence.
A priori, lorsqu'on utilise une fonction, ou une classe, on travaille sur une copie de la variable, d'ou l'intérêt de la ligne "return $result" ou de l'affectation d'une propriété ($this->result = $result)

Le passage d'une variable par référence va signaler que l'on travaille sur la variable elle-même, l'exemple le plus courant étant:
Code PHP :
<?
function increm(&$int) {
   $int++;
}
$a = 2;
echo "a = $a<br />n"; // affiche "a = 2"
increm($a);
echo "a = $a<br />n"; // affiche "a = 3";
?>

Ceux qui connaissent le vb (par exemple) auront reconnu la différence entre function et sub

Dans l'exemple que tu donnes, on demande en fait à la fonction de retourner une référence, le constructeur est alors:
function &classquelconque() {
...
}

De toutes manières, je te conseille d'éviter de te servir de cela car cela provoque des warning en php 4.3+ et des erreurs fatales en php5, ces versions gérant elles-même les références.
bonjour tout le monde,

la question sur les références est intéressante (je les ai jamais utilisé pour un constructeur)
mais à la lecture du post, je me pose une question:
new crée une instance de la classe, donc en théorie, l'objet n'existe pas avant le new
par conséquence quel est la différence entre :

Code :
$instance = &new UneClasse();

et

Code :
$instance = new UneClasse();


la seule raison que je vois est que le constructeur détruit l'instance de la classe et renvoie une référence vers une instance déjà existance ou recréée

ou alors j'ai tout faux Smile

En fait, l'appel d'une classe par référence est une astuce utilisée avant le php 4.3 qui n'a qu'un but, faker un destructeur.
Lorsque tu appelles ta classe par référence, tu peux ensuite faire unset($instance).
Tu as donc détruit l'instance complètement, et non pas une "copie".
Merci crazycat pour les explications donné,

Citation :
En fait, l'appel d'une classe par référence est une astuce utilisée avant le php 4.3 qui n'a qu'un but, faker un destructeur.
Lorsque tu appelles ta classe par référence, tu peux ensuite faire unset($instance).
Tu as donc détruit l'instance complètement, et non pas une "copie".


Sinon je vois pas vraiment pourquoi utilisé les références avec new,et c'est le cas de script Vbulletin dont tous les appels des class sont par references ???

Je voudrais juste signaler en toute généralité que le passage par référence ou par valeur n'a pas que des conséquences au niveau de la programmation. Ca a aussi des conséquences sur les performances : un passage par valeur nécessitant une copie... de la valeur, c'est plus gourmand en ressources qu'un passage par référence. Ce qui explique par exemple que pour les langages de programmation qui privilégient le passage par valeur en général, certains gros objets soient quand même d'office passés par référence (c'est souvent le cas des tableaux).
Et c'est pour cela que le système de gestion des classes de PHP5 gère lui-même l'utilisation ou non du passage par références.

Concernant vbulletin et les gros systèmes multi-utilisateurs, je pense que l'utilisation des références est pour deux raisons:
1) comme l'a dit Yayef, limiter l'utilisation de la mémoire
2) éviter certains effets de bords (une variable modifiée par un autre utilisateur, ça c'est déjà vu)
Pages: 1 2
URLs de référence