Le magasin YBET

Rue Albert 1er, 7

6810 Pin - Chiny

Route Arlon - Florenville

(/fax: 061/32.00.15

Formation en ligne YBET sur le langague PHP - MySQL

YBET Forum webmaster Créer son site

28. La programmation objet (PDO, POO en abrégé)

1. Petit exemple de départ - 2. La méthode Where - 3. La méthode Join

Si vous lisez parfois les codes de certaines solutions en ligne, vous avez probablement déjà rencontré des lignes de commande de type $this-> . C'est la déclaration de variables en programmation objet. Ça sert à quoi?

Dans une programmation standard, vous utilisez des fonctions qui sont souvent utilisées sur plusieurs pages. Cette méthode d'appel de fonctions a un gros défaut: à chaque appel d'une fonction, vous devez revérifier les paramètres à lui transmettre (déjà une perte de temps) mais en plus dans quel ordre les faire passer. En programmation objet, on va rassembler les variables en classes, les regrouper pour chaque "fonction". Pour moi, le réel avantage de cette méthode est liée à la maintenance d'un site programmé. En cours de développement, on a des mécanismes. Par contre en réimplantant de nouvelles fonctions quelques années plus tard sur un site existant, le programmeur doit revoir finalement toutes les fonctions (souvent on réécrit quasiment les mêmes).

Dans la suite, nous allons utiliser un exemple un peu pertinent, la présentation des produits sur un site de vente en ligne. Dans la suite, on va parler:

Rien compris, je parie ...  Reprenons notre exemple. Notre magasin virtuel va reprendre des produits informatiques. Chaque classe va reprendre une catégorie (par exemple les imprimantes et les ... cartouches pour imprimantes). Chaque classe va reprendre des caractéristiques communes (le nom, la description et le prix par exemple). Chaque objet va reprendre la fiche d'un produit et les attributs son nom, description et prix. J'ai volontairement repris les caractéristiques de la classe, pourquoi? Tout simplement parce qu'on va non pas utiliser directement les caractéristiques propres de l'objet mais bien de la classe dans lequel est repris l'objet. Alors pourquoi ne pas reprendre toutes les catégories de produit dans une même classe? Reprenons nos imprimantes et nos cartouches. Qu'est ce qui peut dissocier (dans leurs caractéristiques mais aussi en programmation) ces deux types de produits? Une imprimante est aussi désignée par son numéro de série et une cartouche par les modèles d'imprimantes compatibles. Par contre, toutes les imprimantes ont des caractéristiques identiques (comme une durée de garantie). On pourrait être plus large et séparée les modèles jet d'encre et laser mais ... on va simplement utiliser un attribut des objets pour leur donner une technologie associée. Pour l'instant, on va en rester là (c'est déjà pas si simple).

En programmation objet, l'élément principal est ... l'objet mais avant de créer un objet, on va créer une classe reprenant les caractéristiques des objets qui sont intégrés dans cette classe. C'est la grosse différence entre une programmation de ce type et l'utilisation de fonctions disparates qu'on intègre: le projet doit être préparé d'avance. et pour parfaire, cette méthode va nous débarrasser des variables en tableaux (le plus souvent avec des cases vides).

1. PDO en local.

La majorité des commandes sont directement implantée dans PHP 4.0 et suivant (avec des différences de commandes entre les versions 4 et 5). Nous travaillerons ici sur la version 5. Pour travailler en local, vous pouvez utiliser soit Wampserver, sous EasyPhp dans leurs dernières versions. Pour cette formation, j'utilise à la fois EasyPhp 5.3.2i et Wampserver version 2.0. mais pas sur les mêmes ordinateurs pour éviter des conflits en local.

2. Les classes.

C'est bien ici qu'on doit débuter avant de créer les objets. Reprenons notre catégorie "imprimante". Nous allons la définir comme suit en PHP4 et PHP5 (dans la suite nous utiliserons uniquement les notations de PHP 5)

// en PHP 4

<?php
class Imprimante

{

var $CodeProduit;

var $DescriptionProduit;

}
?>

// en PHP5, on définit trois sortes de variables de la classe: public (accessible à tous), private (uniquement la classe) et protected (classe et sous clases éventuelles)

<?php
class Imprimante

{

public $CodeProduit;

public $DescriptionProduit;

}
?>

 

La première ligne crée une classe nommée imprimante, les lignes suivantes vont déclarées des variables à l'intérieur de cette classe ($CodeProduit et $DescriptionProduit). Remarquez les majuscules dans les noms de ces variables, ce n'est pas une obligation mais cette notation va nous faciliter la vie dans quelques chapitres plus tard (une petite analyse d'un frameworks).

Reste à donner des valeurs avec les lignes suivantes

<?php
$canon540= new Imprimante();

// on crée une variable appelée $canon540

$canon540-> CodeProduit="Canon MP540";

$canon540->DescriptionProduit="Multifonction Pixma MP540";

// on assigne une valeur pour les deux variables 


?>

Première remarque, les variables reprises dans la classe ne sont pas précédée du cigle dollard $. Deuxième remarque, l'affichage se fait par la commande echo() (ou print()) (et de nouveau sans $ pour les variables de la classe, soit:

<?php
echo $canon540->CodeProduit."<br>";

echo $canon540->DescriptionProduit;
?>

Le résultat affiché est 

CanonMP540

Multifonction Pixma MP540

3. Les fonctions inclues dans les classes.

Jusqu'ici, l'utilisation de la programmation PDO (développée objet) ou POO (orientée objet) n'a pas réellement d'intérêt, à part ajouter des lignes de codes. On va pourtant commencer à utiliser les parties intéressante. La première est de pouvoir créer des fonctions accessibles pour une classe (et à ce stade, uniquement pour elle).

Commençons par modifier notre classe:

<?php
class Imprimante

{

public $CodeProduit;

public $DescriptionProduit;

public $StockProduit;

}

$canon540= new Imprimante()

$canon540->StockProduit=5;
?>

On simplement ajouter une variable de stock. Cette variable peut-être augmentée (livraison fournisseur) ou réduite (livraison client). C'est bien là l'idée, inclure directement dans la classe deux fonctions

<?php
class Imprimante

{

public $CodeProduit;

public $DescriptionProduit;

public $StockProduit;

 

function EntreeStock($nombre) {

        $this->StockProduit += $nombre;

    }

function SortieStock($nombre) {

        $this->StockProduit -= $nombre;

    }

}

$canon540= new Imprimante()

$canon540->StockProduit=5;

 

$canon540->EntreeStock(2);

// on ajoute deux imprimantes de ce modèle en stock

$canon540->SortieStock(1);

// on en retire 1
?>

C'est parti ... Reprenons la même chose en programmation normale:

<?php

$imprimante=array();

$imprimante [canon540,code]="Canon MP540";

$imprimante[canon540,description]="Multifonction Pixma MP540";

$imprimante[canon540,stock]=5;

// pour la déclaration de ce modèle, on utilise un tableau, ce qui commence déjà à compliquer la "lecture du programme". mais c'est ensuite que le réel intérêt apparaît.

 

// Comment on va programmer la fonction augmenter ou diminuer le stock?

 

// Première solution (sans fonction), donc à coder à chaque produits pour chaque livraison client ou fournisseur

 

$imprimante[canon540,stock] += $nombre; // on augmente le stock

$imprimante[canon540,stock]-=$nombre; // on diminue le stock

 

 

// et en fonction, c'est pire

// 1. déclaration des deux fonctions valables pour chaque modèle d'imprimante

function EntreeStock($modele,$nombre)

{

$imprimante[$modele,stock] += $nombre;

$stock=$imprimante[$modele,stock];

Return $stock;

}

 

// et 

function SortieStock($modele,$nombre)

{

$imprimante[$modele,stock] += $nombre;

$stock=$imprimante[$modele,stock];

Return $stock;

}

// avec appel des fonctions

$imprimante[$modele,stock]=SortieStock($modele,$nombre);

$imprimante[$modele,stock]=EntreeStock($modele,$nombre);

 

?>

J'avoue ne même pas avoir essayé si ces fonctions ... fonctionnent (c'est tout dire). On va prendre le temps de regarder les lignes de codes avec PDO et avec fonctions.

Dans le premier cas, la déclaration de classe reprend $this-> pour indiquer que pour chaque objet de la classe, ces deux fonctions sont valables: un autre modèle d'imprimante les utilisera de la même manière. Dans le deuxième cas (sans fonctions), on va multiplier le nombres de lignes avec des risques d'erreurs mais surtout un codage difficile à lire et à modifier (à faire pour toutes les pages .... en en oubliant à tous les coups -> de longues heures pour une petite modification, même si de loin, la programmation directe semble la plus facile) et la troisième solution (si elle fonctionne) va poser des problèmes similaires mais surtout un code incompréhensible.

Tiens ça me rappelle mon travail de fin d'étude en assembleur mélangé avec du Basic de l'époque sur Commodore 64 en 1988, personne n'a plus jamais réussi à comprendre le fonctionnement quelques mois plus tard (y compris moi) même si je l'avais adapté pour deux mémoires ou, plus proche, tous les vieux programmes en Fortran qu'on a complètement reprogrammé pour le passage de l'an 2000, faute de pouvoir comprendre le fonctionnement. En programmation, le développement c'est 10% du temps, la maintenance des programmes (corrections, mises à jour et modifications), c'est 90%.

3. Et sans nom de classe?

Dans cet exemple, c'est évident qu'on va nommer le produit avec la commande new() mais ce n'est pas toujours le cas. Prenons un exemple, une remarque à ajouter sur une facture (comme un texte indicatif de remerciement). Cet objet pourra avoir un code et une description mais forcément pas de stock puisque ce n'est pas un produit livré (on aurait pu utiliser également la main-d'oeuvre). Il va falloir dire que le "produit" a un stock de 0 s'il n'est pas initialisé. Reprenons notre déclaration d'objet.

<?php
class Imprimante

{

public $CodeProduit;

public $DescriptionProduit;

public $StockProduit;

 

function imprimante()

{

$this->StockProduit = 0;

}

function EntreeStock($nombre) {

        $this->StockProduit += $nombre;

    }

function SortieStock($nombre) {

        $this->StockProduit -= $nombre;

    }

}


?>

On a juste rajouté une fonction du même nom que l'objet (on appelle çà un constructeur) qui va initialiser la variable $StockProduit à 0 si elle n'est pas mentionnée de chaque objet repris dans la classe. Un seul constructeur peut être utilisé pour un même objet et il est automatiquement appelé lorsqu'on appelle la classe par la ligne de commande:

<?php

$canon540= new Imprimante()


?>

4. Quelques possibilités supplémentaires?

Jusqu'ici, on a déjà pas mal gagné de temps mais on pourrait également ajouter des fonctions supplémentaires dans la classe comme l'affichage ou même le prix de vente, on va même ajouter des paramètres supplémentaires liés aux multiples petites taxes ajoutées à l'informatique comme recupel (pour la récupération des déchets) ou Reprobel (droit pour la reproduction).

<?php
class Imprimante
{
public $CodeProduit;
public $DescriptionProduit;
public $StockProduit;
public $RecupelProduit;
public $ReprobelProduit;
public $PrixVenteProduit;

function imprimante()
{
$this->StockProduit = 0;
$this->RecupelProduit=0;
$this->ReprobelProduit=0;
$this->PrixVenteProduit=0;
}

function AfficherProduit($tvaproduit)
{
echo "Code: ".$this->CodeProduit;
echo "<br>Description: ".$this->DescriptionProduit;
echo "<br>Prix de vente: ".$this->PrixVenteProduit;
echo "<br>Taxe recupel: ".$this->RecupelProduit;
echo "<br>Taxe Reprobel: ".$this->ReprobelProduit;
echo "<br>Prix de vente hTVA: ".($this->PrixVenteProduit + $this->RecupelProduit + $this->ReprobelProduit);
echo "<hr>";
$PrixVenteTtc= ($this->PrixVenteProduit + $this->RecupelProduit + $this->ReprobelProduit)*(1+$tvaproduit);
echo "Prix de Vente TTC: ".$PrixVenteTtc;
Return $PrixVenteTtc;
// on renvoit le prix toutes taxes comprises à la fonction
}

function EntreeStock($nombre)
{
$this->StockProduit +=$nombre;
}

function SortieStock($nombre)
{
$this->StockProduit -=$nombre;

}
}

// début du programme
$canon540= new Imprimante();
$canon540->CodeProduit="CANON 540";

$canon540->DescriptionProduit="Imprimante multifonction";

$canon540->PrixVenteProduit=50;
$canon540->StockProduit=5;

$Prix_TVA_comprise=$canon540->AfficherProduit(0.21);
?>

Devrait vous afficher 

Code: CANON 540
Description: Imprimante multifonction
Prix de vente: 50
Taxe recupel: 0
Taxe Reprobel: 0
Prix de vente hTVA: 50
Prix de Vente TTC: 60.5

Voyons un peu ce petit programme. La classe reprend 4 fonctions. La première (du même nom que la classe est un constructeur qui initialise quelques variables. La deuxième AfficherProduit($tvaproduit) va d'abord afficher l'objet et additionner le prix et les taxes spéciales. Par contre, on lui passe le paramètre $tvaproduit (qui va être augmenter de 1 pour TVA comprise) et la fonction renvoie le prix total TVA comprise. C'est une méthode comme une autre puisqu'on pourrait également créer un attribut dans la classe qui reprendrait ce pourcentage. Les deux fonctions suivantes ont déjà été vues plus haut.

Une autre remarque avec le constructeur, on pourrait donner un code par défaut s'il n'est pas entrée. Les différentes parties de programmes deviennent

<?php
class Imprimante
{

// initialisation de la première variable
public $CodeProduit='sans code';
public $DescriptionProduit;
public $StockProduit=0;
public $RecupelProduit;
public $ReprobelProduit;
public $PrixVenteProduit;

function imprimante($code)
{

if ($code !="") this->CodeProduit=$nom;
}

}

// début du programme
$canon540= new Imprimante(canon540);
$canon540->DescriptionProduit="Imprimante multifonction";

$canon540->PrixVenteProduit=50;
$canon540->StockProduit=5;

?>

On a simplement déclaré l'attribut CodeProduit de la classe à 'sans code'. La fonction constructeur vérifie si un paramètre est passé ($code). S'il l'est, c'est ce nom qui est utilisé comme CodeProduit, sinon, il reste à sa valeur initiale et la fonction va passer le paramètre via la commande $canon540=new Imprimante (code). Ici on a initialisé une variable directement dans la classe (remarquez aussi pour la variable StockProduit).

6. Première analyse

La programmation développée (orientée) objet nous a déjà permis de détacher la partie programme de la partie fonctionnalités. Les exemples suivant vont le faire encore plus mais en utilisant une base de donnée MySQL. On retrouve le véritable intérêt de cette méthode: en séparant les deux, on va en cas de problème ou de modification commencer par modifier la classe et seulement ensuite les quelques lignes de programmes qui vont intervenir sur les attributs. Une dernière chose avant de continuer, ces classes sont souvent reprises dans un fichier à part pour chacune (appelé par include()), ce qui facilite encore plus la maintenance. En deuxième, la propreté du code va encore faciliter le debogage. Le troisième avantage par rapport aux fonctions, c'est qu'on appelle finalement ce qu'on a besoin.

Autres formations en ligne sur ybet.be:

> Mise en ligne du site - Référencement d'un site
<27 . Utilisation des cookies

Mise en ligne: 02/11/2010