Classes et objets

Première leçon du cours PHP orienté objet et Composer, en accès libre : environ 15 minutes, 3 exercices et 3 questions de quiz. C'est la leçon de base du catalogue ; dans l'espace étudiant, elle est réécrite pour ton profil.

Objectifs

  • Déclarer une classe avec des propriétés typées, un constructeur et des méthodes
  • Instancier des objets et appeler leurs méthodes avec ->
  • Utiliser la promotion de constructeur et les propriétés readonly

Classes et objetsConstructeur et promotionPropriétés readonly

Pourquoi des objets ?

Avec des tableaux et des fonctions, les données (un produit) et les traitements (calculer son prix TTC) restent séparés. La programmation orientée objet (POO) les regroupe : une classe décrit un modèle, et chaque objet est un exemplaire concret de ce modèle. C’est l’approche de tous les frameworks PHP modernes (Laravel, Symfony).

Une première classe

<?php
declare(strict_types=1);

class Produit
{
    // Propriétés typées
    public string $nom;
    public float $prixHt;

    // Le constructeur est appelé automatiquement par new
    public function __construct(string $nom, float $prixHt)
    {
        $this->nom = $nom;        // $this = l'objet en cours de construction
        $this->prixHt = $prixHt;
    }

    // Une méthode : une fonction qui appartient à la classe
    public function prixTtc(float $taux = 0.2): float
    {
        return round($this->prixHt * (1 + $taux), 2);
    }
}

$carnet = new Produit("Carnet A5", 6.5);   // instanciation
echo $carnet->nom;                          // Carnet A5
echo $carnet->prixTtc();                    // 7.8

On accède aux propriétés et méthodes avec ->. Par convention, les classes sont nommées en PascalCase, une classe par fichier portant le même nom (Produit.php).

La promotion de constructeur

Depuis PHP 8, on peut déclarer et initialiser les propriétés directement dans la signature du constructeur :

<?php
class Produit
{
    public function __construct(
        public string $nom,
        public float $prixHt,
        public int $stock = 0,        // valeur par défaut
    ) {}                              // corps vide : tout est fait

    public function estDisponible(): bool
    {
        return $this->stock > 0;
    }
}

$tasse = new Produit(nom: "Tasse", prixHt: 9.0, stock: 3); // arguments nommés

C’est la forme la plus courante dans le code actuel.

readonly : des objets immuables

Une propriété readonly ne peut être affectée qu’une seule fois, à l’intérieur de la classe (en pratique dans le constructeur). Toute modification ultérieure lève une Error.

<?php
final class Adresse
{
    public function __construct(
        public readonly string $rue,
        public readonly string $ville,
    ) {}

    // Pour « modifier », on renvoie un nouvel objet
    public function avecVille(string $ville): static
    {
        return clone($this, ['ville' => $ville]);   // PHP 8.5 : copie en changeant ville
    }
}

$a = new Adresse("3 rue des Lilas", "Lyon");
// $a->ville = "Nantes";        // Error : Cannot modify readonly property
$b = $a->avecVille("Nantes");   // $a n'a pas changé

Depuis PHP 8.5, clone($objet, ['propriete' => valeur]) copie l’objet en remplaçant certaines propriétés, même readonly, à condition d’être appelé depuis la classe (comme ici). Avant, on écrivait new static($this->rue, $ville). Piège classique : appeler $a->avecVille("Nantes"); sans récupérer le résultat. En ajoutant l’attribut #[\NoDiscard] (PHP 8.5) au-dessus de la méthode, PHP émet un avertissement quand sa valeur de retour est ignorée. Depuis PHP 8.2, readonly class Adresse { ... } rend toutes les propriétés readonly d’un coup.

Objets et affectation

Une variable contient une poignée vers l’objet, pas une copie :

<?php
$p1 = new Produit("Stylo", 1.2);
$p2 = $p1;          // même objet !
$p2->nom = "Feutre";
echo $p1->nom;      // Feutre
$p3 = clone $p1;    // vraie copie (superficielle)

Enfin, l’opérateur nullsafe ?-> évite les erreurs quand un objet peut être null : $commande?->client?->email renvoie null au lieu de planter.

À retenir

  • class, new, ->, $this : le vocabulaire de base.
  • Préfère la promotion de constructeur et les propriétés typées.
  • readonly pour les valeurs qui ne doivent pas changer après création.

Exercices

Les solutions et les tests restent sur le serveur. Dans l'espace étudiant, ton code est exécuté et corrigé, et le tuteur donne des indices avant la solution.

  1. CodeDifficulté 1Sandbox serveur2 indices

    Classe Produit

    Crée une classe Produit avec la promotion de constructeur : nom (string), prixHt (float), stock (int, 0 par défaut), toutes publiques. Ajoute :

    • prixTtc(float $taux = 0.2): float arrondi à 2 décimales ;
    • estDisponible(): bool (stock strictement positif).
    declare(strict_types=1);
    
    class Produit
    {
        // à compléter
    }
  2. CodeDifficulté 2Sandbox serveur2 indices

    Montant immuable

    Crée une classe final Montant avec une propriété public readonly int $centimes (le montant en centimes évite les erreurs d’arrondi des float). Ajoute :

    • ajouter(Montant $autre): Montant qui renvoie un nouvel objet ;
    • format(): string qui renvoie par exemple "12,50 €" pour 1250 centimes.
    declare(strict_types=1);
    
    final class Montant
    {
        // à compléter
    }
  3. QCMDifficulté 21 indice

    Affectation d'objets

    Après $a = new Produit("Stylo", 1.0); $b = $a; $b->nom = "Feutre";, que vaut $a->nom ?

    • "Stylo"
    • "Feutre"
    • null
    • Une erreur

Quiz de fin de leçon

  1. Quel mot-clé crée une instance d’une classe ?

    • class
    • new
    • create
  2. Que permet la promotion de constructeur ?

    • Hériter d'une autre classe
    • Déclarer et initialiser des propriétés directement dans les paramètres du constructeur
    • Rendre le constructeur statique
  3. Que se passe-t-il si on modifie une propriété readonly déjà initialisée ?

    • La nouvelle valeur est ignorée
    • Une Error est levée
    • La propriété devient publique

La suite du cours

  1. Encapsulation et héritage18 min
  2. Interfaces, polymorphisme et traits18 min
  3. Membres statiques, constantes et énumérations16 min
  4. Gérer les erreurs avec les exceptions16 min
  5. Namespaces, Composer et autoload PSR-420 min

PHP orienté objet et Composer · Intermédiaire · 3 h 13