Tutoriel
Partie 22 — PHP orienté objet : classes, objets, héritage (bases)

Partie 22 — PHP orienté objet : classes, objets, héritage (bases)

Apprends la programmation orientée objet en PHP : classes/objets, constructeur, visibilité, encapsulation, héritage, override, static, exemples réels et mini-projet.

PHP 65 Mis à jour 16 hours ago
Conseil : lisez d’abord les sections clés, puis essayez un QCM lié à la même notion pour valider votre compréhension.

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: écrire name au lieu de $this->name)
  • Confondre public et private (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)

  1. Créer une classe User avec name, email (email private + getter/setter).
  2. Créer une classe AdminUser qui hérite de User (role = admin).
  3. Créer une méthode canAccessAdmin().
  4. Créer une classe PostRepository (find/create/update/delete) avec PDO.
  5. 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.