POO en PHP : guide complet de la programmation orientée objet (2026)
La programmation orientée objet (POO) en PHP est incontournable pour les projets sérieux. Ce guide complet couvre les classes, l'héritage, les interfaces, les traits et les patterns modernes avec des exemples concrets en PHP 8.
La POO en PHP est la base de tous les frameworks modernes (Symfony, Laravel) et de WordPress lui-même. Maîtriser les objets, l’héritage et les interfaces vous rend capable de lire et d’écrire du code PHP professionnel. Ce guide part de zéro et va jusqu’aux patterns avancés.
Classes et objets : les fondamentaux
Une classe est un plan de construction, un objet est une instance de ce plan :
class Article {
public string $title;
public string $content;
private DateTime $createdAt;
public function __construct(string $title, string $content) {
$this->title = $title;
$this->content = $content;
$this->createdAt = new DateTime();
}
public function getSummary(): string {
return mb_substr($this->content, 0, 100) . '...';
}
public function getCreatedAt(): DateTime {
return $this->createdAt;
}
}
$article = new Article('Mon titre', 'Contenu de l'article...');
echo $article->getSummary();
Visibilité : public, protected, private
public — accessible depuis n’importe où. protected — accessible dans la classe et ses enfants. private — accessible uniquement dans la classe. En PHP moderne, exposez le moins possible : commencez par private, passez à protected si une classe enfant en a besoin, à public uniquement si l’API externe en a besoin.
Héritage
Une classe peut étendre une autre pour hériter de ses propriétés et méthodes :
class Post extends Article {
public array $categories = [];
public function __construct(string $title, string $content, array $categories) {
parent::__construct($title, $content);
$this->categories = $categories;
}
public function getSummary(): string {
return '[Post] ' . parent::getSummary();
}
}
Attention à l’héritage profond : une chaîne de plus de 2-3 niveaux devient difficile à maintenir. Préférez la composition à l’héritage quand c’est possible.
Interfaces
Une interface définit un contrat : toute classe qui l’implémente doit avoir ces méthodes :
interface Serializable {
public function serialize(): string;
public function unserialize(string $data): void;
}
class JsonArticle extends Article implements Serializable {
public function serialize(): string {
return json_encode(['title' => $this->title, 'content' => $this->content]);
}
public function unserialize(string $data): void {
$d = json_decode($data, true);
$this->title = $d['title'];
$this->content = $d['content'];
}
}
Traits
Les traits permettent de réutiliser du code dans plusieurs classes sans héritage :
trait Timestampable {
private DateTime $createdAt;
private DateTime $updatedAt;
public function touch(): void {
$this->updatedAt = new DateTime();
}
public function getUpdatedAt(): DateTime {
return $this->updatedAt;
}
}
class Article {
use Timestampable;
// Article a maintenant les méthodes touch() et getUpdatedAt()
}
Classes abstraites
Une classe abstraite définit un comportement partiel que les classes enfants doivent compléter :
abstract class BaseRepository {
abstract protected function getTableName(): string;
public function findAll(): array {
// Implémentation commune utilisant getTableName()
return $this->query("SELECT * FROM {$this->getTableName()}");
}
}
class ArticleRepository extends BaseRepository {
protected function getTableName(): string { return 'articles'; }
}
PHP 8 : constructor promotion et named arguments
PHP 8 a simplifié considérablement le code des classes :
// Avant PHP 8 — verbeux
class User {
public string $name;
public string $email;
public function __construct(string $name, string $email) {
$this->name = $name;
$this->email = $email;
}
}
// PHP 8+ — constructor promotion
class User {
public function __construct(
public readonly string $name,
public readonly string $email
) {}
}
// Named arguments
$user = new User(email: 'a@b.fr', name: 'Alice');
Injection de dépendances
Le pattern le plus important de la POO moderne : passer les dépendances depuis l’extérieur plutôt que de les créer à l’intérieur :
// Mauvais : couplage fort
class ArticleService {
private MySQLArticleRepository $repo;
public function __construct() {
$this->repo = new MySQLArticleRepository(); // impossible à mocker pour les tests
}
}
// Bon : injection de dépendances
class ArticleService {
public function __construct(
private ArticleRepositoryInterface $repo // injecté depuis l'extérieur
) {}
}
C’est le principe derrière les conteneurs d’injection de dépendances de Symfony et Laravel. Maîtriser ce pattern est indispensable pour écrire du PHP testable et maintenable.