Les Traits en PHP, un outil puissant trop peu utilisé ?
PHP ne permet pas l’héritage multiple. Pour contourner cette limite, les Traits ont été introduits à partir de PHP 5.4. Ils permettent d’injecter des méthodes dans plusieurs classes sans les faire hériter d’une même classe parente.
Mal utilisés, ils peuvent nuire à la lisibilité et à la maintenabilité. Bien maîtrisés, ils sont un excellent outil pour structurer du code partagé. Voici un tour d’horizon des usages, bonnes pratiques et pièges à éviter.
1. Pourquoi les Traits ?
En PHP, une classe ne peut hériter que d’une seule autre classe. Les Traits permettent de factoriser du comportement réutilisable dans des classes différentes.
trait LoggerTrait {
public function log(string $message): void {
echo "[LOG] $message\n";
}
}
class ServiceA {
use LoggerTrait;
}
class ServiceB {
use LoggerTrait;
}
2. Cas d’usage concrets
Les Traits sont utiles pour encapsuler des comportements transverses.
Logger partagé
trait LoggerTrait {
public function log(string $message): void {
echo date('Y-m-d H:i:s') . " - $message\n";
}
}
Suppression logique (soft delete)
trait SoftDeleteTrait {
private ?\DateTime $deletedAt = null;
public function delete(): void {
$this->deletedAt = new \DateTime();
}
public function isDeleted(): bool {
return $this->deletedAt !== null;
}
}
3. Bonnes pratiques
Un Trait = une responsabilité
Éviter les traits fourre-tout. Chaque Trait doit avoir un rôle précis.
Méthodes explicites
Des noms clairs évitent les collisions. Préférer handleForm()
à handle()
.
Pas de dépendances implicites
Un Trait ne doit pas supposer l’existence d’une propriété ou méthode sans la définir ou l’injecter clairement.
// Mauvais
trait BrokenTrait {
public function doSomething(): void {
$this->repository->save(); // dépendance cachée
}
}
// Correct
trait WellDefinedTrait {
protected RepositoryInterface $repository;
public function setRepository(RepositoryInterface $repo): void {
$this->repository = $repo;
}
public function doSomething(): void {
$this->repository->save();
}
}
4. Pièges à éviter
Collisions de méthodes
Deux traits avec une méthode du même nom nécessitent une résolution explicite.
class C {
use A, B {
B::sayHello insteadof A;
}
}
Utilisation excessive
Accumuler trop de Traits dans une même classe nuit à la clarté.
Fausse abstraction
Les Traits ne remplacent pas un vrai design orienté objet. Si vous avez besoin de polymorphisme ou de hiérarchie, préférez les interfaces ou classes abstraites.
5. Alternatives
- Interface + classe abstraite : plus contraignant, mais plus clair.
- Composition : déléguer les responsabilités à d’autres objets.
- Services dédiés : dans Symfony, injecter un service est souvent plus propre.
Conclusion
Les Traits sont un outil utile pour structurer du code partagé, à condition de les utiliser avec modération et rigueur.
En résumé :
- Limitez leur responsabilité.
- Évitez les dépendances implicites.
- Préférez la composition dès que les Traits deviennent lourds.
Bien utilisés, les Traits simplifient. Mal utilisés, ils complexifient. À vous de trancher.
Et vous ?
Connaissiez-vous les traits en PHP ? Partagez vos retours ou astuces en me rejoignant sur LinkedIn — je serai ravi d’en discuter !