Aller au contenu
M07 · B. Programmer en PHP

L'orienté objet en PHP : classes, objets, encapsulation

Pourquoi programmer en objet en PHP, écrire une classe avec propriétés et méthodes, le constructeur (et sa forme courte), $this, la visibilité public / private / protected, getters et setters, constantes et membres statiques.

1Situer

Au module 03, vous avez appris la POO en Python. Le site de Souk Atlas grossit : produits, clients, paniers, commandes. Plutôt que des tableaux et des fonctions éparpillés, on regroupe chaque notion dans une classe qui contient ses données et ses règles. C'est aussi ainsi que sont écrits PDO, DateTime et tous les frameworks PHP (Laravel, Symfony).

2Comprendre

Une classe, plusieurs objets
class Produit - string $nom - float $prix - int $stock + __construct(...) + vendre($qte) + afficher() - private + public $tajine nom = 'Tajine décoré' prix = 180 stock = 14 $savon nom = 'Savon noir' prix = 30 stock = 120

La classe Produit est le moule : elle déclare des propriétés (nom, prix, stock) et des méthodes (vendre, afficher).

1 / 5

Pourquoi programmer en objet en PHP ?

Ce que la POO apporte à un site PHP :

  • regrouper : tout ce qui concerne un produit (prix, stock, calcul TTC, vente) est au même endroit ;
  • protéger : le stock ne peut pas devenir négatif si on passe obligatoirement par vendre() ;
  • réutiliser : la même classe Produit sert au catalogue, au panier et à l’administration ;
  • lire du code existant : PDO, DateTime, les exceptions et les frameworks sont des classes.

Classe, propriétés, méthodes, objets

class Produit
{
    public string $nom;
    public float $prix;

    public function prixTtc(): float
    {
        return $this->prix * 1.2;
    }
}

$savon = new Produit();
$savon->nom = "Savon noir";
$savon->prix = 30;
echo $savon->prixTtc();   // 36

$this désigne l’objet sur lequel la méthode est appelée : dans $savon->prixTtc(), $this est $savon. Par convention, le nom d’une classe commence par une majuscule, et on range chaque classe dans un fichier du même nom (Produit.php).

Le constructeur

class Produit
{
    // forme courte (PHP 8) : déclare et remplit $nom, $prix et $stock
    public function __construct(
        public string $nom,
        private float $prix,
        private int $stock = 0,
    ) {}
}

$tajine = new Produit("Tajine décoré", 180, 14);

Forme longue équivalente : déclarer public string $nom; en haut de la classe, puis $this->nom = $nom; dans le constructeur.

Encapsulation : public, private, protected

class Produit
{
    public function __construct(public string $nom, private float $prix, private int $stock = 0) {}

    public function getStock(): int
    {
        return $this->stock;
    }

    public function vendre(int $quantite): void
    {
        if ($quantite > $this->stock) {
            throw new Exception("Stock insuffisant pour {$this->nom}");
        }
        $this->stock -= $quantite;
    }
}

$p = new Produit("Tapis berbère", 1200, 3);
try {
    $p->vendre(5);
} catch (Exception $e) {
    echo $e->getMessage();
}

throw new Exception("...") signale une erreur ; try { ... } catch (Exception $e) { ... } l’attrape pour afficher un message propre au lieu d’une erreur fatale.

Constantes de classe et membres statiques

class Produit
{
    public const TVA = 0.20;
    private static int $nombre = 0;

    public function __construct(public string $nom)
    {
        self::$nombre++;
    }

    public static function nombre(): int
    {
        return self::$nombre;
    }
}

new Produit("Tajine");
new Produit("Savon");
echo Produit::nombre(), " produits, TVA ", Produit::TVA * 100, " %";
Exemple simple

Le plan et les maisons

La classe est le plan de l'architecte ; chaque objet est une maison construite d'après ce plan, avec sa propre adresse et sa propre couleur de porte. new Produit(...) construit une maison.

Exemple simple

Le distributeur automatique

On ne met pas la main dans le distributeur pour prendre une canette : on passe par les boutons (les méthodes publiques). Le stock à l'intérieur est privé : c'est l'encapsulation.

3Manipuler

La classe Produit est dans Produit.php. Complétez la méthode vendre() et le getter, puis utilisez la classe dans index.php.
Pas à pas dans le lab ↗ Cliquez sur Exécuter : PHP 8.3 démarre dans votre navigateur (environ 5 Mo à télécharger, une seule fois).

La page s'affichera ici.

Le navigateur demandera /index.php au serveur, qui exécutera le PHP et renverra du HTML.

Entre le navigateur et le serveur aucun échange pour l'instant

Consignes 0 / 3

  1. La page affiche le prix TTC du tajine : 216 DH
  2. Après la vente de 2 tapis : « Stock du tapis : 1 »
  3. La vente de 5 tapis est refusée : « Stock insuffisant pour Tapis berbère »

4Pratiquer

Exercice 1 · Classe Client

Écrivez une classe Client avec nom, prénom et email (privé), un constructeur, une méthode nomComplet() et un setter setEmail() qui refuse un email invalide.

Voir le corrigé
<?php
class Client
{
    private string $email = '';

    public function __construct(public string $nom, public string $prenom, string $email)
    {
        $this->setEmail($email);
    }

    public function nomComplet(): string
    {
        return "$this->prenom " . strtoupper($this->nom);
    }

    public function setEmail(string $email): void
    {
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            throw new InvalidArgumentException("Email invalide : $email");
        }
        $this->email = strtolower($email);
    }

    public function getEmail(): string
    {
        return $this->email;
    }
}
$c = new Client("Benali", "Amina", "Amina.Benali@mail.ma");
echo $c->nomComplet() . " - " . $c->getEmail();

Exercice 2 · Compteur statique

Ajoutez à Produit une propriété statique $nombre qui compte les produits créés, et affichez-la après la création de trois produits.

Voir le corrigé
<?php
class Produit
{
    public static int $nombre = 0;
    public function __construct(public string $nom)
    {
        self::$nombre++;
    }
}
new Produit("Tajine"); new Produit("Savon"); new Produit("Tapis");
echo Produit::$nombre;   // 3

Exercice 3 · Un panier objet

Écrivez une classe Panier avec un tableau privé de lignes, une méthode ajouter(Produit $p, int $qte) et une méthode total().

Voir le corrigé
<?php
class Panier
{
    private array $lignes = [];

    public function ajouter(Produit $p, int $qte = 1): void
    {
        $this->lignes[] = ['produit' => $p, 'qte' => $qte];
    }

    public function total(): float
    {
        $t = 0;
        foreach ($this->lignes as $l) {
            $t += $l['produit']->prixTtc() * $l['qte'];
        }
        return $t;
    }
}

5Vérifier

1. Comment accède-t-on à une propriété d'un objet en PHP ?
2. Une propriété private est accessible :
3. Dans une méthode, que désigne $this ?