Hébergement du site en PHP et Mysql par WDMédia-hébergement
Vous aussi adpotez les éléPHPants de Vincent Pontier !  
CONCOURS
 
 
PLUS DE PHP
 
 
PLUS DE JAVASCRIPT
 
COMMENT CA MARCHE
 
 
EXPLIQUE-MOI
 
 
NEWS LETTER
 

 
PARTENAIRES
 
Découvrez scriptsphp.org
Découvrez phpteam.net
Tout sur les expressions régulières
IE sucks :-)
 
DESIGN DU SITE
 
Classes et objets I
La sortie de PHP5 va amener à revoir ce tuto de Nikoh, qui reste valable pour PHP4.


Première partie: Les classes et les objets

Voila un thème assez particulier et je dirai même très différent des autres tutorials de phpdebutant.com. Certains trouveront ces concepts difficiles ou même inutiles. Sachez néanmoins que la POO est la méthode majeure de programmation dans de nombreux languages (C++, Java, JavaScript...) et qu'elle possède des avantages indéniables. Restons-en là pour le blabla et passons aux choses sérieuses.

Prérequis: Les bases du PHP, déclaration de variables, visibilité des variables, les fonctions en PHP

I) Qu'est ce que c'est ?

La POO est une manière de programmer un peu différente de celle que vous pouviez utiliser jusqu'à présent en PHP. En effet, le corps de vos scripts était toujours composé de plusieurs fonctions. La POO va un peu bousculer tout cela, mais pour votre bien vous verrez.

La POO a deux buts (plus d'autres légèrement plus subtils que nous ne traiterons pas ici):
- faciliter la réutilisation du code que vous avez déjà écrit: c'est l'héritage (cf Tutorial suivant)
- l'encapsulation des données et les traitements correspondants (ce Tutorial)

II) Un premier exemple d'encapsulation et de traitement

Jusqu'ici, tout vous parait obscur, nous allons donc étudier un exemple (il vaut ce qu'il vaut, et de toutes façon, il y a à peu près le même dans la documentation officielle de PHP).
Imaginons que vous vouliez gérer les commandes d'une pizzeria pour chaque client (vous étiez prévenu...). Vous devez donc, pour chaque client: mémoriser son nom, comptabiliser le type des pizzas commandées, leur nombre et enfin calculer le prix total de la commande.

Jusqu'à présent, vous auriez défini de nombreuses variables pour chaque client, ou mieux un tableau. Nous allons voir une autre façon de le faire, en utilisant une classe:

a) Le nom du client
<?
class Commande {
    var 
$nomClient;
}
?>

Voila déjà une première partie. Passons aux explications:
La classe "Commande" déclarée ci-dessus contient une variable dite "variable membre" nommée $nomClient.
L'utilisation est assez simple:


<?

//on indique à PHP que la variable $client contiendra
//des données définies dans la classe Commande
$client = new Commande();  

//pour la variable $client, qui est de type "Commande",
//on donne à la variable membre $nomClient la valeur "PHPDebutant"
$client->nomClient="PHPDebutant";    
?>
Et vous pouvez vérifer que:

echo $client->nomClient;
renvoie bien "PHPDebutant".

A ce stade, vous allez me dire que c'est beaucoup de travail pour un bien maigre résultat...patience !

b) La liste des pizzas commandées

On va modifier la classe Commande pour y ajouter une autre variable membre afin de gérer la liste des pizzas. Pour simplifier, on utilisera un tableau:


<?

class Commande {
    var 
$nomClient;
    var 
$listePizzas;
}

$client = new Commande();  
$client->nomClient="PHPDebutant";
$client->listePizzas[0] = 5;  // disons que 0 est le code pour "Pizza Royale", j'en veux 5
$client->listePizzas[1] = 2;  // je veux deux "Campagnarde" (n°1)


?>

La encore, pas grand chose de neuf, l'indice du tableau correspondant à un type de pizza.
Maintenant, il faut constater quelquechose. Vous avez vu que l'ajout de nouveaux éléments n'était pas très intuitif. On va donc ajouter des fonctions membres:

c) Ajouter des pizzas

<?

class Commande {
    var 
$nomClient;
    var 
$listePizzas;

    function 
ajouterRoyale($nombre) {
        
$this->listePizzas[0] += $nombre;
    }

    function 
ajouterCampagnarde($nombre) {
        
$this->listePizzas[1] += $nombre;
    }
}

$client = new Commande();  
$client->nomClient="PHPDebutant";
$client->ajouterRoyale(5);  // je veux 5 "Pizza Royale"
$client->ajouterCampagnarde(2);  // je veux deux "Campagnarde"
?>

Et ici, l'interet des classes commence à apparaitre (mais la route est encore longue). En effet, en plus des variables membres définies depuis le début, on a ajouté des fonctions membres. Qu'est ce qu'une fonction membre ? Il s'agit d'une fonction qui a pour but d'intervenir sur les variables membres de la classe. Le mot clé $this est en fait identique à la variable d'appel. Je m'explique:


<?

$client1 
= new Commande();  
$client1->nomClient="PHPDebutant";
$client1->ajouterRoyale(5);  // je veux 5 "Pizza Royale"

$client2 = new Commande();  
$client2->nomClient="Anne";
$client2->ajouterRoyale(1);  // elle veux 1 "Pizza Royale" (régime...)
?>

Lors de l'appel $client1->ajouterRoyale(5); la variable $this de la fonction membre ajouterRoyale prendra la valeur $client1 et c'est donc sur les variables membres de celle-ci que s'effectura l'ajout. Lors de l'appel $client2->ajouterRoyale(1); $this prendra la valeur $client2

d) Pour compléter...

Pour obtenir ce que nous voulions depuis le début:

<?php

class Commande {
    
// définissons les variables correspondant au prix (en euros bien sur) des pizzas.
    // On leur donne une valeur par défaut.
    // Petit exercice euro, ces pizzas sont elles chères ou pas ?
    
var $prixRoyale 6;
    
var $prixCampagnarde 8;
    
// et les variables qu'on connait déjà
    
var $nomClient;
    var 
$listePizzas;

    function 
ajouterRoyale($nombre) {
        
$this->listePizzas[0] += $nombre;
    }

    function 
ajouterCampagnarde($nombre) {
        
$this->listePizzas[1] += $nombre;
    }

    function 
calculerPrix() {
        
$montant_Royale $this->listePizzas[0] * $this->prixRoyale;
        
$montant_Campagnarde $this->listePizzas[1] * $this->prixCampagnarde;
        return 
$montant_Royale $montant_Campagnarde;
    }


    function 
afficherCommande() {
        echo 
"Commande du client : ".$this->nomClient;
        echo 
"<BR>Pizza(s) 'Royale' : ".$this->listePizzas[0];
        echo 
"<BR>Pizza(s) 'Campagnarde' : ".$this->listePizzas[1];
        echo 
"<HR>Totale de votre commande : ".$this->calculerPrix();    
        
// on peut également appeller des fonctions membres
        
echo " Euros<BR>";
    }
}
$client1 = new Commande();  
$client1->nomClient="PHPDebutant";
$client1->ajouterRoyale(5);
$client1->ajouterCampagnarde(2);
$client1->afficherCommande();
?>

Ce qui donne:
Commande du client : PHPDebutant
Pizza(s) 'Royale' : 5
Pizza(s) 'Campagnarde' : 2
Total de votre commande : 46 Euros

Attention: Une erreur très fréquente est d'écrire les appels comme suit:
$this->$nomClient
Ceci ne renverra pas d'erreur, mais le résultat ne sera pas celui attendu.
Il ne faut jamais placer, dans cette syntaxe, de signe $ devant le nom du variable membre. Ici, il fallait donc écrire:
$this->nomClient
J'insiste lourdement sur cette erreur, car elle vient naturellement...

Nous avons donc écrit une classe tout à fait fonctionnelle. L'interêt est assez important. Il est vrai que vous avez écrit pas mal de code pour un maigre résultat mais, il y a des avantages indéniables:

  • Clarté du code: la classe peut être placée dans un fichier séparé que l'on appellera via la commande include(). L'utilisation de l'opérateur -> rend le code clair et compréhensible.
  • Facilité de réutilisation: la clarté du code facilite la réutilisation du code dans d'autres projets et même par d'autres personnes. Cet aspect sera développé gràce à l'héritage (cf Tutorial suivant)
III) Constructeur de classe

Pour compléter cette présentation des classes, il reste un aspect important mais simple à traiter: le constructeur de classe.
En effet, en considérant notre cher exemple des pizzas, vous pouvez remarquer que le champ $nomClient peut ne pas être initialisé:


<?php

class Commande {
    
// Identique à ce qui a été défini précedemment
}
$client1 = new Commande();  
$client1->ajouterRoyale(5);
$client1->ajouterCampagnarde(2);
$client1->afficherCommande();

?>

Ce qui donne:
Commande du client :
Pizza(s) 'Royale' : 5
Pizza(s) 'Campagnarde' : 2
Total de votre commande : 46 Euros

Le nom du client est vide, en va corriger ce problème en plaçant un nom par défaut (ex: SansNom)
C'est le constructeur de classe qui va s'en charger. Le constructeur est en fait une fonction membre qui porte impérativement le même nom que la classe. Cette fonction est appellée automatiquement lors de la création d'un objet (donc au moment de l'appel $client1 = new Commande();)
C'est donc le moment privilégié pour réaliser les initialisations que l'on désire.

a) Un nom par défaut

Pour cela, il suffit de modifier la classe Commande:


<?php

class Commande {
    var 
$prixRoyale 6;
    var 
$prixCampagnarde 8;
    var 
$nomClient;
    var 
$listePizzas;

    
//Constructeur de la classe car même nom:
    
function Commande() {    
        
$this->nomClient "SansNom";
    }

    function 
ajouterRoyale($nombre) {
        
$this->listePizzas[0] += $nombre;
    }

    function 
ajouterCampagnarde($nombre) {
        
$this->listePizzas[1] += $nombre;
    }

    function 
calculerPrix() {
        
$montant_Royale $this->listePizzas[0] * $this->prixRoyale;
        
$montant_Campagnarde $this->listePizzas[1] * $this->prixCampagnarde;
        return 
$montant_Royale $montant_Campagnarde;
    }


    function 
afficherCommande() {
        echo 
"Commande du client : ".$this->nomClient;
        echo 
"<BR>Pizza(s) 'Royale' : ".$this->listePizzas[0];
        echo 
"<BR>Pizza(s) 'Campagnarde' : ".$this->listePizzas[1];
        echo 
"<HR>Totale de votre commande : ".$this->calculerPrix();
        echo 
" Euros<BR>";
    }
}
$client1 = new Commande();  
$client1->ajouterRoyale(5);
$client1->ajouterCampagnarde(2);
$client1->afficherCommande();


?>

Ce qui donne:
Commande du client : SansNom
Pizza(s) 'Royale' : 5
Pizza(s) 'Campagnarde' : 2
Total de votre commande : 46 Euros
Merci.

La fonction membre Commande() est un constructeur car elle possède le même nom que la classe. Elle est appellée en premier et initialise la variable membre à la valeur "SansNom".
Bien sûr, il est toujours possible de modifier le nom du client avec $client1->$nomClient="PHPDebutant";
De plus tout ceci est équivalent à avoir déclaré une valeur par défaut:
var $nomClient = "SansNom";

b) Paramètres du constructeur

On vient de voir que le constructeur permet d'initialiser les variables membres et plus généralement, d'effectuer divers traitement initiaux.

Dans notre exemple, le nom du client ne devrais pas changer et on peut donc le choisir à la création de l'objet, et donc se charger de cette initialisation dans la constructeur.

Il suffit donc de modifier le constructeur en lui ajoutant un paramètre. De plus, dans le code qui suit, la variable $nomClient contient maintenant une valeur par défaut.


<?php

class Commande {
    var 
$prixRoyale 6;
    var 
$prixCampagnarde 8;
    var 
$nomClient "SansNom";
    var 
$listePizzas;

    
//Constructeur avec paramètre
    
function Commande($nom) {    
        if (
$nom != ""$this->nomClient $nom;
    }
    
    function 
ajouterRoyale($nombre) {
        
$this->listePizzas[0] += $nombre;
    }

    function 
ajouterCampagnarde($nombre) {
        
$this->listePizzas[1] += $nombre;
    }

    function 
calculerPrix() {
        
$montant_Royale $this->listePizzas[0] * $this->prixRoyale;
        
$montant_Campagnarde $this->listePizzas[1] * $this->prixCampagnarde;
        return 
$montant_Royale $montant_Campagnarde;
    }

    function 
afficherCommande() {
        echo 
"Commande du client : ".$this->nomClient;
        echo 
"<BR>Pizza(s) 'Royale' : ".$this->listePizzas[0];
        echo 
"<BR>Pizza(s) 'Campagnarde' : ".$this->listePizzas[1];
        echo 
"<HR>Totale de votre commande : ".$this->calculerPrix();
        echo 
" Euros<BR>";
    }
}

$client = new Commande("PHPDebutant");
$client->ajouterRoyale(2);
$client->ajouterCampagnarde(3);
$client->afficherCommande();



?>

Ce qui donne:
Commande du client : PHPDebutant
Pizza(s) 'Royale' : 2
Pizza(s) 'Campagnarde' : 3
Totale de votre commande : 36 Euros


Remarques:
Il ne peut exister qu'un seul constructeur par classe.

Il est conseillé de placer chaque classe dans un fichier portant le nom de cette classe (ex: Commande.class.php) et d'utiliser des include(). Ceci sera très pratique pour la suite.


IV) Vocabulaire, utilité et conclusion

Pour commencer, un peu de vocabulaire:

  • On dit que "Commande" est une classe.
  • $client = new Commande("PHPDebutant");
    On dit alors que $client est un objet de type "Commande". On dit également que $client est une instance de la classe "Commande".
  • "variable membre" et "variable d'instance" sont synonymes.
  • "fonction membre" et "méthode" sont synonymes.

Il est tout à fait possible de créer des objets d'une autre classe au sein même d'une classe. Ainsi, on aurait ici pu créer un objet de type "MoyenDePaiement" dans la classe "Commande". Ces liens entre les classes sont TRES utilisés.

De plus la notion de constructeur est très importante en PHP car elle permet d'initialiser les variables de la classe, notamment avec une base de données MySQL (lecture dans une table et affectation aux variables membres). Dans ce cas, il resterait à écrire une fonction membre permettant de sauvegarder les variables membres dans un table SQL.

Ceci dit, comment utiliser les notions de programmation objet vues précedemment dans vos projets ?
Le cas de la commande des pizzas peut aisément se rapprocher d'un "shopping cart" comme on en trouve sur les sites marchands.
Mais globalement, le concept de programmation par objet peut s'appliquer à tous les problèmes.

Quelle que soit l'application, le schéma est souvent le même, un objet est créé à l'entrée sur le site et est conservé tout le long de la navigation via l'utilisation des sessions. Ainsi, vous pouvez créer une classe Visiteur qui mémorisera toutes les actions d'un visiteur (arrivée sur une page, clic sur un lien, etc...) et vous pourrez facilement créer des statistiques ou autres informations plus complexes.

Une fois que toutes ces bases ont été vues, il nous restera à voir:

  • L'héritage: pour pouvoir créer de nouvelles classes basées sur une classe déjà existante en ajoutant ou modifiant des fonctions membres. (Nous verons également le polymorphisme)
  • La serialisation: pour sauvegarder/charger des objets à partir de fichiers
Et eventuellement quelques exemples concrets...



Ajouter une réponse
Nom
Email
Titre

Mise en forme : gras = [b]...[/b], italic = [i]...[/i], souligné = [u]...[/u], citation = [quote]...[/quote], lien = [url]liens_externe[/url] ou [url nom=texte]liens_externe[/url], code source : [code]...[/code]

Mémoriser mon nom et mon email : Oui Non
www.phpdebutant.org © 2017 - L'équipe de phpDebutant - Hébergement : WDMédia-hébergement
DEBUTEZ !
 
  0.  Introduction
  1.  Afficher une phrase ou une image
  2.  Afficher la date et l'heure
  3.  PHP dans du code HTML
  4.  La concaténation
  5.  Récupérer les valeurs d'un formulaire
  6.  Les structures de contrôle
  7.  Ecrire et lire dans un fichier texte
  8.  Les fonctions utilisateurs
  9.  Les variables d'environnement
  10.  Quelques fonctions utiles
  11.  SQL/MySQL (Create, Alter & Drop)
  12.  SQL/MySQL (Insert et Select)
  13.  SQL/MySQL (Delete et Update)
  14.  SQL/MySQL (Where)
  15.  Fonctions PHP pour mySQL
  16.  Interroger une table MySQL
  17.  Alimenter une ou plusieurs tables mySQL
  18.  Les pseudos-frames
  19.  Les sessions php4
  20.  Affichage page par page
  21.  Images dynamiques
  22.  Ca marche pas ?
  23.  Variables globales à OFF
  24.  Les variables dynamiques