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.
readonlypour 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.
Classe Produit
Crée une classe
Produitavec la promotion de constructeur :nom(string),prixHt(float),stock(int, 0 par défaut), toutes publiques. Ajoute :prixTtc(float $taux = 0.2): floatarrondi à 2 décimales ;estDisponible(): bool(stock strictement positif).
declare(strict_types=1); class Produit { // à compléter }Montant immuable
Crée une classe
finalMontantavec une propriétépublic readonly int $centimes(le montant en centimes évite les erreurs d’arrondi des float). Ajoute :ajouter(Montant $autre): Montantqui renvoie un nouvel objet ;format(): stringqui renvoie par exemple"12,50 €"pour 1250 centimes.
declare(strict_types=1); final class Montant { // à compléter }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
Quel mot-clé crée une instance d’une classe ?
- class
- new
- create
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
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
- Encapsulation et héritage18 min
- Interfaces, polymorphisme et traits18 min
- Membres statiques, constantes et énumérations16 min
- Gérer les erreurs avec les exceptions16 min
- Namespaces, Composer et autoload PSR-420 min