Partie 22 — PHP orienté objet : classes, objets, héritage (bases)
Jusqu’ici, on a écrit du PHP “procédural” : des variables, des fonctions, des fichiers. Ça marche très bien pour apprendre. Mais dès que le projet grandit (CRUD, auth, API, dashboard…), tu veux une organisation plus solide. C’est là que la programmation orientée objet (POO) devient utile.
La POO, ce n’est pas un truc “théorique”. C’est une façon de structurer ton code pour le rendre :
- plus lisible
- plus réutilisable
- plus facile à maintenir
- plus logique (surtout quand tu as des “entités” : User, Post, Category…)
👉 Dans cette Partie 22 : classes/objets, propriétés/méthodes, constructeur, visibilité (public/private/protected), encapsulation, héritage, override, et exemples concrets comme en vrai projet.
1) Classe vs Objet : comprendre avec une analogie simple
Imagine que tu veux créer des utilisateurs. Tu peux stocker des variables :
$name, $email, etc. Mais si tu as 10 000 users ?
Tu veux un modèle.
Classe = le plan (le “moule”)
Objet = une instance créée à partir de ce plan (un exemplaire réel)
✅ Exemple : Classe User = la définition.
Objet $user1 = un utilisateur réel.
2) Première classe PHP : propriétés + méthodes
Une classe contient :
- propriétés : données (nom, email…)
- méthodes : comportements (saluer, vérifier un rôle…)
<?php
class User
{
public string $name;
public string $email;
public function sayHello(): string
{
return "Bonjour, je suis " . $this->name;
}
}
$user1 = new User();
$user1->name = "Amine";
$user1->email = "amine@test.com";
echo $user1->sayHello();
?>
Le mot $this représente l’objet courant.
Donc $this->name signifie : la propriété name de cet objet.
3) Constructeur : initialiser un objet proprement
Au lieu de créer un objet puis remplir ses champs un par un, tu peux utiliser
un constructeur (__construct).
<?php
class User
{
public function __construct(
public string $name,
public string $email
) {}
public function sayHello(): string
{
return "Bonjour, " . $this->name;
}
}
$user = new User("Salma", "salma@test.com");
echo $user->sayHello();
?>
✅ Cette syntaxe (promotion des propriétés) rend le code très propre en PHP moderne.
4) Visibilité : public / private / protected (encapsulation)
La visibilité contrôle qui peut accéder à une propriété/méthode :
- public : accessible partout
- private : accessible seulement dans la classe
- protected : accessible dans la classe + classes enfants
L’idée : encapsulation = protéger l’état interne de l’objet. Exemple : tu ne veux pas qu’on mette un email invalide n’importe comment.
4.1 Exemple : email privé + méthode setter
<?php
class User
{
private string $email;
public function __construct(
public string $name,
string $email
) {
$this->setEmail($email);
}
public function setEmail(string $email): void
{
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new InvalidArgumentException("Email invalide");
}
$this->email = $email;
}
public function getEmail(): string
{
return $this->email;
}
}
$user = new User("Amine", "amine@test.com");
echo $user->getEmail();
?>
Ici, on ne peut pas faire $user->email = "xxx" parce que $email est private.
Ça force l’utilisation de setEmail() qui valide.
5) Héritage : extends (réutiliser un comportement)
L’héritage sert à créer une classe plus spécifique à partir d’une classe plus générale.
Exemple : AdminUser est un User, mais avec plus de permissions.
<?php
class User
{
public function __construct(
public string $name,
protected string $role = "user"
) {}
public function role(): string
{
return $this->role;
}
public function canAccessAdmin(): bool
{
return $this->role === "admin";
}
}
class AdminUser extends User
{
public function __construct(string $name)
{
parent::__construct($name, "admin");
}
}
$u = new User("Karim");
$a = new AdminUser("Salma");
echo $u->role(); // user
echo $a->role(); // admin
?>
parent::__construct() appelle le constructeur du parent.
On fixe le rôle à “admin”.
6) Override : redéfinir une méthode (polymorphisme simple)
Une classe enfant peut redéfinir une méthode du parent. C’est utile quand tu veux le même nom de méthode mais un comportement différent.
<?php
class User
{
public function label(): string
{
return "Utilisateur";
}
}
class AdminUser extends User
{
public function label(): string
{
return "Administrateur";
}
}
$users = [new User(), new AdminUser()];
foreach ($users as $u) {
echo $u->label() . "<br>";
}
?>
Même si tu parcours un tableau d’objets, chaque objet répond avec sa propre version. C’est un début de polymorphisme.
7) Static et constantes : quand tu n’as pas besoin d’un objet
Parfois, tu veux une méthode “outil” ou une constante globale de classe.
7.1 Constante
<?php
class Security
{
public const MIN_PASSWORD = 8;
}
echo Security::MIN_PASSWORD;
?>
7.2 Méthode statique
<?php
class Slug
{
public static function make(string $text): string
{
$text = strtolower(trim($text));
$text = preg_replace("/[^a-z0-9]+/i", "-", $text);
return trim($text, "-");
}
}
echo Slug::make("Partie 22 — PHP Orienté Objet !");
?>
✅ static est pratique pour des helpers. Mais dès que tu as un “état” (user, panier),
un objet est souvent plus logique.
8) Exemple réel : passer ton repository PDO en POO (propre)
Tu peux transformer tes fonctions post_create, post_find en une classe.
C’est très utilisé dans les frameworks.
<?php
class PostRepository
{
public function __construct(private PDO $pdo) {}
public function find(int $id): ?array
{
$stmt = $this->pdo->prepare("SELECT * FROM posts WHERE id = :id LIMIT 1");
$stmt->execute(["id" => $id]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
return $row ?: null;
}
public function create(string $title, string $body, string $status): int
{
$stmt = $this->pdo->prepare("
INSERT INTO posts (title, body, status, created_at)
VALUES (:t, :b, :s, NOW())
");
$stmt->execute(["t" => $title, "b" => $body, "s" => $status]);
return (int)$this->pdo->lastInsertId();
}
}
$repo = new PostRepository(db());
$newId = $repo->create("Hello", "Contenu...", "draft");
$post = $repo->find($newId);
?>
Avantage : tu passes $pdo une fois, puis tu utilises des méthodes claires.
9) Erreurs fréquentes (et comment les éviter)
-
Oublier
$this->dans une méthode (ex: écrirenameau lieu de$this->name) -
Confondre
publicetprivate(trop tout public = pas d’encapsulation) - Faire de la POO “pour faire de la POO” : si une fonction suffit, garde simple
-
Abuser de
static(ça devient difficile à tester / maintenir) - Ne pas valider les données dans les setters/constructeurs quand c’est nécessaire
✅ La POO sert à clarifier, pas à compliquer. Si ton code devient plus simple à lire, c’est gagné.
10) Exercices (pour être à l’aise)
- Créer une classe
Useravecname,email(email private + getter/setter). - Créer une classe
AdminUserqui hérite deUser(role = admin). - Créer une méthode
canAccessAdmin(). - Créer une classe
PostRepository(find/create/update/delete) avec PDO. - Créer un helper statique
Slug::make()pour générer des slugs.
Conclusion
Tu as maintenant les bases solides de la POO en PHP : classes, objets, constructeur, visibilité, encapsulation et héritage. C’est exactement ce qu’il faut pour comprendre Laravel/Symfony et construire une architecture plus propre.
Partie 23 logique : Interfaces + classes abstraites (POO avancée), ou Namespaces + Autoload (Composer) pour structurer un vrai projet.