Aujourd'hui, nous explorons les concepts avancés de la Programmation Orientée Objet en PHP :
l'héritage, la visibilité, les méthodes statiques, les constantes, les interfaces et les traits.
1. Héritage avec extends
Créer une hiérarchie de classes
<?php
class Personne {
protected
$nom;
protected
$prenom;
protected
$age;
public function __construct($nom, $prenom, $age) {
$this->nom =
$nom;
$this->prenom =
$prenom;
$this->age =
$age;
}
public function sePresenter() {
return
"Je m'appelle $this->prenom $this->nom et j'ai $this->age ans.";
}
}
class Etudiant extends Personne {
private
$ecole;
private
$niveau;
public function __construct($nom, $prenom, $age,
$ecole, $niveau) {
parent::__construct($nom, $prenom,
$age);
$this->ecole =
$ecole;
$this->niveau =
$niveau;
}
public function etudier() {
return
"$this->prenom étudie en $this->niveau à $this->ecole.";
}
public function sePresenter() {
return
parent::sePresenter() .
" Je suis étudiant en $this->niveau.";
}
}
$personne = new Personne("Dupont", "Jean", 45);
$etudiant = new Etudiant("Martin", "Marie", 20, "Sorbonne",
"Master 2");
echo $personne->sePresenter() .
"<br>";
echo $etudiant->sePresenter() .
"<br>";
echo $etudiant->etudier();
?>
Résultat :
Je m'appelle Jean Dupont et j'ai 45 ans.
Je m'appelle Marie Martin et j'ai 20 ans. Je suis étudiant en Master 2.
Marie étudie en Master 2 à Sorbonne.
Concepts clés de l'héritage :
- extends : Hériter d'une classe parente
- parent:: : Appeler une méthode de la classe parente
- override : Redéfinir une méthode du parent dans l'enfant
-
La classe enfant hérite de TOUTES les propriétés et méthodes publiques/protected du
parent
2. Visibilité : public, private, protected
Contrôler l'accès aux propriétés et méthodes
| Visibilité |
Accessible depuis la classe |
Accessible depuis une classe enfant |
Accessible depuis l'extérieur |
| public |
Oui |
Oui |
Oui |
| protected |
Oui |
Oui |
Non |
| private |
Oui |
Non |
Non |
Exemple pratique
<?php
class CompteBancaire {
public
$titulaire;
protected
$numero;
private
$solde;
public function __construct($titulaire, $numero, $soldeInitial) {
$this->titulaire =
$titulaire;
$this->numero =
$numero;
$this->solde =
$soldeInitial;
}
public function getSolde() {
return
$this->solde;
}
public function deposer($montant) {
if ($montant
> 0) {
$this->solde += $montant;
return
"Dépôt de $montant€ effectué. Nouveau solde : " .
$this->solde . "€";
}
return
"Montant invalide.";
}
public function retirer($montant) {
if ($montant
> 0 && $montant <= $this->solde)
{
$this->solde -= $montant;
return
"Retrait de $montant€ effectué. Nouveau solde : " .
$this->solde . "€";
}
return
"Solde insuffisant ou montant invalide.";
}
private function verifierSolde() {
return
$this->solde >= 0;
}
}
$compte = new CompteBancaire("Jean Dupont", "FR123456", 1000);
echo $compte->titulaire .
"<br>";
echo $compte->getSolde() .
"<br>";
echo $compte->deposer(500) .
"<br>";
?>
Pourquoi utiliser private/protected ?
- Encapsulation : Protéger les données sensibles (solde bancaire)
- Contrôle : Valider les données avant modification
-
Maintenance : Changer l'implémentation interne sans casser le code
externe
-
Sécurité : Empêcher la modification directe de propriétés critiques
3. Méthodes et propriétés static
Membres partagés entre toutes les instances
<?php
class Utilisateur {
public
$nom;
private static
$compteur = 0;
public function __construct($nom) {
$this->nom =
$nom;
self::$compteur++;
}
public static function
getNombreUtilisateurs() {
return
self::$compteur;
}
public static function validerEmail($email) {
return
filter_var($email,
FILTER_VALIDATE_EMAIL) !== false;
}
}
echo "Utilisateurs au départ : " .
Utilisateur::getNombreUtilisateurs() . "<br>";
$user1 = new Utilisateur("Jean");
$user2 = new Utilisateur("Marie");
$user3 = new Utilisateur("Paul");
echo "Utilisateurs créés : " .
Utilisateur::getNombreUtilisateurs() . "<br>";
if (Utilisateur::validerEmail("test@example.com")) {
echo
"Email valide !";
}
?>
Résultat :
Utilisateurs au départ : 0
Utilisateurs créés : 3
Email valide !
Quand utiliser static ?
- Compteurs : Compter les instances créées
-
Utilitaires : Fonctions qui ne dépendent pas d'un objet (validation,
formatage)
- Configuration : Stocker des valeurs partagées
- Factory methods : Créer des objets de manière spécialisée
4. Constantes de classe
Valeurs immuables au niveau de la classe
<?php
class Configuration {
const VERSION =
"1.0.0";
const NOM_APP =
"MonSuperSite";
const MAX_UPLOAD_SIZE = 5242880;
public static function afficherInfo() {
echo
"Application : " . self::NOM_APP .
"<br>";
echo
"Version : " . self::VERSION .
"<br>";
echo
"Taille max upload : " . (self::MAX_UPLOAD_SIZE / 1024 / 1024) . " Mo";
}
}
echo Configuration::VERSION .
"<br>";
echo Configuration::NOM_APP .
"<br>";
Configuration::afficherInfo();
?>
Exemple : Statuts d'utilisateur
<?php
class Utilisateur {
const STATUT_ACTIF = 1;
const STATUT_INACTIF = 0;
const STATUT_SUSPENDU = 2;
const ROLE_USER =
"user";
const ROLE_ADMIN =
"admin";
const ROLE_MODERATEUR =
"moderateur";
private
$nom;
private
$statut;
private
$role;
public function __construct($nom, $role = self::ROLE_USER) {
$this->nom =
$nom;
$this->statut =
self::STATUT_ACTIF;
$this->role =
$role;
}
public function estActif() {
return
$this->statut ===
self::STATUT_ACTIF;
}
public function estAdmin() {
return
$this->role ===
self::ROLE_ADMIN;
}
}
$user = new Utilisateur("Jean", Utilisateur::ROLE_ADMIN);
if ($user->estAdmin()) {
echo
"Accès administrateur accordé.";
}
?>
5. Interfaces
Définir un contrat
<?php
interface Affichable {
public function afficher();
public function afficherResume();
}
class Article implements Affichable
{
private
$titre;
private
$contenu;
public function __construct($titre, $contenu) {
$this->titre =
$titre;
$this->contenu =
$contenu;
}
public function afficher() {
return
"<h2>$this->titre</h2><p>$this->contenu</p>";
}
public function afficherResume() {
return
"$this->titre : " . substr($this->contenu, 0, 50) . "...";
}
}
class Produit implements Affichable
{
private
$nom;
private
$prix;
public function __construct($nom, $prix) {
$this->nom =
$nom;
$this->prix =
$prix;
}
public function afficher() {
return
"<h3>$this->nom</h3><p>Prix : $this->prix €</p>";
}
public function afficherResume() {
return
"$this->nom ($this->prix €)";
}
}
function afficherElement(Affichable
$element) {
echo
$element->afficher();
}
$article = new Article("PHP POO", "Apprendre la programmation orientée objet...");
$produit = new Produit("Laptop", 999.99);
afficherElement($article);
afficherElement($produit);
?>
Interfaces vs Classes abstraites :
- Interface : Définit QUOI faire (aucune implémentation)
-
Classe abstraite : Définit QUOI et peut définir COMMENT (peut avoir des
méthodes implémentées)
- Une classe peut implémenter PLUSIEURS interfaces, mais hériter d'UNE SEULE classe
6. Traits
Réutiliser du code entre classes
<?php
trait Horodatage {
private
$dateCreation;
private
$dateModification;
public function setDateCreation() {
$this->dateCreation = date("Y-m-d H:i:s");
}
public function setDateModification() {
$this->dateModification = date("Y-m-d H:i:s");
}
public function getDateCreation() {
return
$this->dateCreation;
}
}
trait Identifiable {
private
$id;
public function setId($id) {
$this->id =
$id;
}
public function getId() {
return
$this->id;
}
}
class Article {
use Horodatage, Identifiable;
private
$titre;
private
$contenu;
public function __construct($id, $titre, $contenu) {
$this->setId($id);
$this->titre =
$titre;
$this->contenu =
$contenu;
$this->setDateCreation();
}
}
class Utilisateur {
use Horodatage, Identifiable;
private
$nom;
public function __construct($id, $nom) {
$this->setId($id);
$this->nom =
$nom;
$this->setDateCreation();
}
}
$article = new Article(1,
"Mon article", "Contenu...");
echo "Article ID : " .
$article->getId() .
"<br>";
echo "Créé le : " .
$article->getDateCreation();
?>
Quand utiliser les traits ?
- Partager du code entre classes sans héritage
- Éviter la duplication de code
- Ajouter des fonctionnalités transversales (logs, timestamps...)
- Alternative à l'héritage multiple (PHP ne supporte pas l'héritage multiple)
Froggiesplaining :
Objectifs de ce cours :
✅ Maîtriser l'héritage avec extends et parent::
✅ Comprendre les modificateurs de visibilité (public, protected, private)
✅ Utiliser les membres static et les constantes
✅ Implémenter des interfaces pour définir des contrats
✅ Utiliser les traits pour partager du code entre classes
Points clés à retenir :
• Héritage = Etudiant extends Personne (grenouille savante qui hérite des capacités
de base)
• public = Accessible partout (ma couleur verte visible par tous)
• protected = Accessible dans la classe et ses enfants (mon ADN familial)
• private = Accessible uniquement dans la classe (mes pensées secrètes)
• static = Partagé par toutes les instances (compteur de grenouilles dans la
mare)
• const = Valeurs immuables (COULEUR_DEFAUT = "vert")
• Interface = Contrat définissant QUOI faire (Nageable impose nager())
• Trait = Code réutilisable sans héritage (lunettes portables par tous)
Exercice pratique :
1. Créer une classe CompteBancaire avec propriétés private (solde, titulaire)
2. Ajouter des méthodes public pour accéder/modifier le solde de façon contrôlée
3. Créer une classe CompteEpargne qui extends CompteBancaire
4. Ajouter une constante TAUX_INTERET et une méthode static calculerInterets()
5. Créer une interface Transferable avec méthode transferer()
6. Implémenter l'interface dans CompteBancaire
7. Conseil de Froggie: Utilise private pour protéger les données sensibles comme mon solde bancaire
de mouches !