🏗️ Article 5 — Introduction à la Programmation Orientée Objet (POO) en PHP
Guide complet pour comprendre les concepts fondamentaux de la POO en PHP. Apprenez à créer des classes, objets, propriétés et méthodes avec des exemples concrets.
🎯 Objectif
Découvrir les concepts de base de la POO en PHP et apprendre à créer des classes, objets, propriétés et méthodes simples pour structurer votre code efficacement.
1️⃣ Introduction
Qu'est-ce que la Programmation Orientée Objet ?
La Programmation Orientée Objet (POO) est un paradigme de programmation qui organise le code autour du concept d'"objets" plutôt que d'actions et de logique. Elle permet de modéliser le monde réel de manière plus naturelle et intuitive.
Pourquoi utiliser la POO en PHP ?
La POO offre de nombreux avantages pour le développement PHP moderne :
- Réutilisabilité du code : Les classes peuvent être réutilisées dans différents projets
- Maintenance facilitée : Le code est mieux organisé et plus facile à modifier
- Évolutivité : L'ajout de nouvelles fonctionnalités est plus simple
- Sécurité : L'encapsulation protège les données sensibles
- Collaboration : Plusieurs développeurs peuvent travailler sur le même projet plus efficacement
Objectif de cet article
Notre objectif est de vous apprendre à :
- Comprendre les concepts fondamentaux de la POO
- Créer vos premières classes et objets en PHP
- Maîtriser l'encapsulation et l'héritage
- Appliquer les bonnes pratiques pour un code professionnel
2️⃣ Concepts clés de la POO
a. Classe et Objet
Une classe est un plan ou modèle qui définit la structure et le comportement. Un objet est une instance concrète créée à partir de cette classe.
<?php
class Utilisateur {
public $nom;
public $email;
}
// ✅ CRÉATION D'OBJETS (INSTANCES)
$user1 = new Utilisateur();
$user1->nom = "Alice";
$user1->email = "alice@example.com";
$user2 = new Utilisateur();
$user2->nom = "Bob";
$user2->email = "bob@example.com";
?>
🔧 Analogie pratique :
Une classe est comme le plan d'une maison. Un objet est la maison construite à partir de ce plan. Vous pouvez construire plusieurs maisons (objets) à partir du même plan (classe).
b. Propriétés et Méthodes
Les propriétés sont les variables d'une classe (caractéristiques). Les méthodes sont les fonctions d'une classe (comportements).
<?php
class Utilisateur {
// Propriétés (attributs)
public $nom;
public $email;
// Méthodes (comportements)
public function afficherNom() {
echo "Nom : " . $this->nom;
}
public function afficherEmail() {
echo "Email : " . $this->email;
}
}
// Utilisation
$user = new Utilisateur();
$user->nom = "Alice";
$user->email = "alice@example.com";
$user->afficherNom(); // Affiche : Nom : Alice
?>
💡 Le mot-clé $this :
$this fait référence à l'objet courant. Il permet d'accéder aux propriétés et méthodes de l'objet depuis l'intérieur de la classe.
c. Constructeur
Le constructeur est une méthode spéciale appelée automatiquement lors de la création d'un nouvel objet. Il permet d'initialiser les propriétés.
<?php
class Utilisateur {
public $nom;
public $email;
// Constructeur
public function __construct($nom, $email) {
$this->nom = $nom;
$this->email = $email;
}
}
// Création d'objet avec le constructeur
$user = new Utilisateur("Alice", "alice@example.com");
echo $user->nom; // Affiche : Alice
echo $user->email; // Affiche : alice@example.com
?>
d. Encapsulation (public, private, protected)
L'encapsulation permet de contrôler l'accès aux propriétés et méthodes d'une classe. Trois niveaux de visibilité existent :
<?php
class Utilisateur {
// Propriété privée (accessible uniquement dans la classe)
private $nom;
private $email;
// Constructeur
public function __construct($nom, $email) {
$this->setNom($nom);
$this->setEmail($email);
}
// Getter pour nom
public function getNom() {
return $this->nom;
}
// Setter pour nom avec validation
public function setNom($nom) {
if (strlen($nom) > 2) {
$this->nom = $nom;
} else {
throw new Exception("Le nom doit contenir au moins 3 caractères");
}
}
// Getter pour email
public function getEmail() {
return $this->email;
}
// Setter pour email avec validation
public function setEmail($email) {
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
$this->email = $email;
} else {
throw new Exception("Email invalide");
}
}
}
// Utilisation
$user = new Utilisateur("Alice", "alice@example.com");
echo $user->getNom(); // Affiche : Alice
?>
📊 Tableau des niveaux d'accès :
| Visibilité | Accès depuis la classe | Accès depuis les classes enfants | Accès depuis l'extérieur |
|---|---|---|---|
public |
✅ Oui | ✅ Oui | ✅ Oui |
protected |
✅ Oui | ✅ Oui | ❌ Non |
private |
✅ Oui | ❌ Non | ❌ Non |
e. Héritage
L'héritage permet à une classe (enfant) d'hériter des propriétés et méthodes d'une autre classe (parent).
<?php
// Classe parent
class Utilisateur {
protected $nom;
protected $email;
public function __construct($nom, $email) {
$this->nom = $nom;
$this->email = $email;
}
public function afficherInfos() {
echo "Utilisateur : $this->nom ($this->email)";
}
}
// Classe enfant qui hérite de Utilisateur
class Admin extends Utilisateur {
private $niveauAcces = "admin";
public function afficherRole() {
echo "Rôle : Administrateur";
}
// Redéfinition (surcharge) de la méthode parente
public function afficherInfos() {
echo "Administrateur : $this->nom ($this->email) - Niveau : $this->niveauAcces";
}
}
// Utilisation
$admin = new Admin("Alice", "admin@example.com");
$admin->afficherInfos(); // Méthode redéfinie
$admin->afficherRole(); // Méthode spécifique à Admin
?>
f. Polymorphisme (optionnel pour débutants)
Le polymorphisme permet à une méthode de se comporter différemment selon l'objet qui l'appelle.
<?php
class Animal {
public function faireDuBruit() {
echo "L'animal fait un bruit";
}
}
class Chien extends Animal {
public function faireDuBruit() {
echo "Wouf Wouf !";
}
}
class Chat extends Animal {
public function faireDuBruit() {
echo "Miaou !";
}
}
// Utilisation polymorphe
$animaux = [
new Chien(),
new Chat(),
new Animal()
];
foreach ($animaux as $animal) {
$animal->faireDuBruit(); // Comportement différent selon l'objet
echo "<br>";
}
?>
3️⃣ Exemple pratique complet
Voyons maintenant un exemple complet qui rassemble tous les concepts vus précédemment :
<?php
// Classe de base Utilisateur
class Utilisateur {
protected $id;
protected $nom;
protected $email;
protected $dateInscription;
public function __construct($id, $nom, $email) {
$this->id = $id;
$this->setNom($nom);
$this->setEmail($email);
$this->dateInscription = date('Y-m-d H:i:s');
}
// Getters
public function getId() { return $this->id; }
public function getNom() { return $this->nom; }
public function getEmail() { return $this->email; }
public function getDateInscription() { return $this->dateInscription; }
// Setters avec validation
public function setNom($nom) {
if (strlen($nom) < 2) {
throw new Exception("Le nom doit contenir au moins 2 caractères");
}
$this->nom = htmlspecialchars($nom);
}
public function setEmail($email) {
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new Exception("Email invalide");
}
$this->email = $email;
}
// Méthode pour afficher les informations
public function afficherProfil() {
echo "ID : " . $this->getId() . "<br>";
echo "Nom : " . $this->getNom() . "<br>";
echo "Email : " . $this->getEmail() . "<br>";
echo "Inscrit le : " . $this->getDateInscription() . "<br>";
}
}
// Classe Admin qui hérite de Utilisateur
class Admin extends Utilisateur {
private $niveauAcces;
public function __construct($id, $nom, $email, $niveauAcces = "moderateur") {
parent::__construct($id, $nom, $email);
$this->setNiveauAcces($niveauAcces);
}
public function getNiveauAcces() {
return $this->niveauAcces;
}
public function setNiveauAcces($niveau) {
$niveauxAutorises = ["moderateur", "administrateur", "superadmin"];
if (in_array($niveau, $niveauxAutorises)) {
$this->niveauAcces = $niveau;
} else {
throw new Exception("Niveau d'accès non autorisé");
}
}
// Redéfinition de la méthode afficherProfil
public function afficherProfil() {
parent::afficherProfil();
echo "Niveau d'accès : " . $this->getNiveauAcces() . "<br>";
}
// Méthode spécifique à Admin
public function supprimerUtilisateur($utilisateurId) {
echo "L'administrateur $this->nom a supprimé l'utilisateur ID : $utilisateurId";
}
}
// Utilisation du système
echo "<h3>Création d'utilisateurs</h3>";
// Création d'un utilisateur normal
$user1 = new Utilisateur(1, "Alice Dupont", "alice@example.com");
$user1->afficherProfil();
echo "<hr>";
// Création d'un administrateur
$admin1 = new Admin(2, "Bob Admin", "bob@example.com", "administrateur");
$admin1->afficherProfil();
echo "<hr>";
// Utilisation des méthodes spécifiques
$admin1->supprimerUtilisateur(1);
?>
4️⃣ Bonnes pratiques
Conventions de nommage
📝 Règles de nommage recommandées :
- Classes : PascalCase (
Utilisateur,GestionnaireUtilisateurs) - Méthodes : camelCase (
getNom(),afficherProfil()) - Propriétés : camelCase (
$nomUtilisateur,$dateCreation) - Constantes : MAJUSCULES (
STATUT_ACTIF,TYPE_ADMIN)
Encapsulation et sécurité
<?php
class Produit {
// Toujours déclarer les propriétés en private ou protected
private $id;
private $nom;
private $prix;
// Utiliser des getters pour l'accès en lecture
public function getId() {
return $this->id;
}
public function getNom() {
return $this->nom;
}
// Utiliser des setters avec validation pour la modification
public function setPrix($prix) {
if (!is_numeric($prix) || $prix < 0) {
throw new InvalidArgumentException("Le prix doit être un nombre positif");
}
$this->prix = floatval($prix);
}
// Méthodes métier plutôt que propriétés publiques
public function appliquerRemise($pourcentage) {
$reduction = $this->prix * ($pourcentage / 100);
$this->prix -= $reduction;
return $this->prix;
}
}
?>
Documentation du code
<?php
/**
* Classe représentant un utilisateur du système
*
* @package Application\Model
* @author WebIntelligence
* @version 1.0
*/
class Utilisateur {
/**
* @var int Identifiant unique de l'utilisateur
*/
private $id;
/**
* @var string Nom complet de l'utilisateur
*/
private $nom;
/**
* Crée une nouvelle instance d'Utilisateur
*
* @param int $id Identifiant unique
* @param string $nom Nom complet
* @param string $email Adresse email valide
* @throws InvalidArgumentException Si l'email est invalide
*/
public function __construct($id, $nom, $email) {
// ... implémentation
}
/**
* Retourne le nom complet de l'utilisateur
*
* @return string Le nom de l'utilisateur
*/
public function getNom() {
return $this->nom;
}
}
?>
💡 Bonnes pratiques supplémentaires :
- Une classe = une responsabilité (principe de responsabilité unique)
- Évitez les classes trop grosses (divisez les responsabilités)
- Utilisez l'injection de dépendances plutôt que de créer des objets dans les classes
- Préférez la composition à l'héritage quand c'est possible
- Écrivez des tests unitaires pour vos classes
5️⃣ Conclusion
✅ Récapitulatif des concepts clés :
- Classes et objets : Plans et instances concrètes
- Propriétés et méthodes : Caractéristiques et comportements
- Constructeurs : Initialisation des objets
- Encapsulation : Protection des données avec public, private, protected
- Héritage : Réutilisation du code entre classes
- Polymorphisme : Comportements différents selon le contexte
Avantages de la POO pour vos projets
- Code plus organisé : Structure claire et logique
- Réutilisabilité : Classes réutilisables dans différents projets
- Maintenance facilitée : Modifications locales sans affecter le système
- Évolutivité : Ajout de fonctionnalités plus simple
- Sécurité : Contrôle d'accès aux données sensibles
- Collaboration : Travail d'équipe plus efficace
🚀 Prochain article
Dans notre prochain tutoriel, nous approfondirons les concepts avancés de la POO en PHP !
👉 "POO Avancée en PHP : Interfaces, Traits et Design Patterns"
Découvrez les interfaces, les traits, les classes abstraites et les design patterns pour maîtriser complètement la programmation orientée objet en PHP.
Questions Fréquentes sur la POO en PHP
Quelle est la différence entre une classe et un objet ?
Une classe est un plan ou modèle qui définit la structure (propriétés) et le comportement (méthodes). Un objet est une instance concrète créée à partir de cette classe. Par exemple, "Voiture" est une classe, tandis "ma BMW rouge" est un objet.
Quand dois-je utiliser public, private ou protected ?
Utilisez private pour les propriétés/méthodes accessibles uniquement dans la classe elle-même. protected pour celles accessibles dans la classe et ses classes enfants. public pour celles accessibles de partout. En général, préférez private et utilisez des getters/setters pour contrôler l'accès.
Quelle est la différence entre l'héritage et l'interface ?
L'héritage (extends) permet à une classe d'hériter du code d'une autre classe (propriétés et méthodes). Une interface (implements) définit un contrat que la classe doit respecter (quelles méthodes elle doit implémenter) sans fournir d'implémentation.
Dois-je toujours utiliser des getters et setters ?
Pas toujours, mais c'est une bonne pratique. Les getters/setters permettent de contrôler l'accès aux propriétés, d'ajouter de la validation, et de modifier l'implémentation interne sans affecter le code qui utilise la classe. Pour les objets simples (DTO), les propriétés publiques peuvent être acceptables.