Utilisation de plusieurs Traits
Fait partie de la section Programmation Orientée Objet du Journey PHP de Coddy — leçon 52 sur 91.
Un seul trait est utile, mais la véritable puissance réside dans la combinaison de plusieurs traits au sein d'une même classe. PHP vous permet d'inclure autant de traits que nécessaire, offrant à votre classe des capacités provenant de plusieurs sources à la fois.
Pour utiliser plusieurs traits, il suffit de les lister en les séparant par des virgules après le mot-clé use :
<?php
trait Timestampable {
public function getTimestamp(): string {
return date('Y-m-d H:i:s');
}
}
trait Identifiable {
private string $id;
public function generateId(): void {
$this->id = uniqid('id_');
}
public function getId(): string {
return $this->id;
}
}
class Post {
use Timestampable, Identifiable;
public function __construct(public string $title) {
$this->generateId();
}
}
$post = new Post("Hello World");
echo $post->getId() . " - " . $post->getTimestamp();
Sortie :
id_6789abc123 - 2024-01-15 10:30:00La classe Post possède désormais des méthodes issues des deux traits. Chaque trait apporte sa propre fonctionnalité : Timestampable fournit des méthodes liées au temps, tandis que Identifiable gère les identifiants uniques. Cette approche permet à chaque trait de rester concentré sur une seule responsabilité, rendant votre code plus modulaire et réutilisable.
Que se passe-t-il lorsque deux traits ont des méthodes portant le même nom ? C'est une situation de conflit que nous explorerons dans la prochaine leçon.
Défi
FacileConstruisons un système de gestion de produits qui combine plusieurs traits pour donner aux produits des capacités de tarification et d'inventaire. Chaque trait gérera une seule responsabilité, et votre classe de produit gagnera des fonctionnalités des deux.
Vous organiserez votre code sur trois fichiers :
Priceable.php— Créez un trait appeléPriceablequi gère les fonctionnalités de tarification. Le trait doit avoir :- Une propriété privée
$price(float) - Une méthode
setPrice(float $price)qui stocke le prix - Une méthode
getPrice()qui retourne le prix - Une méthode
getFormattedPrice()qui retourne le prix formaté comme"$[price]"avec 2 décimales
- Une propriété privée
Stockable.php— Créez un trait appeléStockablequi gère l'inventaire. Le trait doit avoir :- Une propriété privée
$stock(integer) - Une méthode
setStock(int $quantity)qui stocke la quantité en stock - Une méthode
getStock()qui retourne le stock actuel - Une méthode
isInStock()qui retournetruesi le stock est supérieur à 0,falsesinon
- Une propriété privée
main.php— Incluez les deux fichiers de traits et créez une classeProductqui utilise les deux traitsPriceableetStockable. Utilisez la promotion de constructeur pour définir une propriété publique$name. Le constructeur doit également accepter un prix et une quantité en stock, en utilisant les méthodes des traits pour les définir.Vous recevrez trois entrées : un nom de produit, un prix et une quantité en stock. Créez un produit avec ces valeurs et affichez quatre lignes :
- Le nom du produit
- Le prix formaté (en utilisant
getFormattedPrice()) - La quantité en stock
"Available"si en stock, ou"Out of stock"sinon
Cela démontre comment plusieurs traits fonctionnent ensemble — votre classe Product gagne des capacités de tarification d'un trait et la gestion d'inventaire d'un autre, gardant chaque préoccupation proprement séparée tout en les combinant dans un produit complet.
Aide-mémoire
Pour utiliser plusieurs traits dans une classe, listez-les séparés par des virgules après le mot-clé use :
<?php
trait Timestampable {
public function getTimestamp(): string {
return date('Y-m-d H:i:s');
}
}
trait Identifiable {
private string $id;
public function generateId(): void {
$this->id = uniqid('id_');
}
public function getId(): string {
return $this->id;
}
}
class Post {
use Timestampable, Identifiable;
public function __construct(public string $title) {
$this->generateId();
}
}
$post = new Post("Hello World");
echo $post->getId() . " - " . $post->getTimestamp();
// Résultat : id_6789abc123 - 2024-01-15 10:30:00
Chaque trait apporte sa propre fonctionnalité à la classe. Cette approche permet à chaque trait de rester concentré sur une seule responsabilité, rendant le code plus modulaire et réutilisable.
Essayez vous-même
<?php
require_once 'Priceable.php';
require_once 'Stockable.php';
// TODO: Créer une classe Product qui utilise les traits Priceable et Stockable
// Utiliser la promotion de constructeur pour la propriété publique $name
// Le constructeur doit accepter name, price, et stock, et utiliser les méthodes des traits pour définir le prix et le stock
class Product {
// TODO: Utiliser les traits ici
// TODO: Implémenter le constructeur avec la promotion de constructeur pour $name
// et définir le prix et le stock en utilisant les méthodes des traits
}
// Lire l'entrée
$name = trim(fgets(STDIN));
$price = floatval(trim(fgets(STDIN)));
$stock = intval(trim(fgets(STDIN)));
// TODO: Créer une instance de Product avec les valeurs d'entrée
// TODO: Afficher le nom du produit
// TODO: Afficher le prix formaté en utilisant getFormattedPrice()
// TODO: Afficher la quantité en stock
// TODO: Afficher "Available" si en stock, ou "Out of stock" sinon
?>Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation Orientée Objet
1Les bases de la POO
Fichiers externesIntroduction à la POOClasses vs ObjetsLe mot-clé $thisMéthodesPropriétésConstructeur (__construct)Destructeur (__destruct)Récapitulatif - Calculatrice simple4Héritage
Héritage de baseLe mot-clé parent::Redéfinition de méthodeLe mot-clé finalClasses abstraitesRécapitulatif - Hiérarchie des employés7Encapsulation
Public, Protégé, PrivéModificateurs d'accès en détailGetters et SettersMasquage d'informationPromotion de constructeur (8.0)Récapitulatif - Système de gestion d'étudiants10Concepts avancés de la POO
Composition vs HéritageInjection de dépendancesClasses anonymesÉnumérations (PHP 8.1)Fibers (PHP 8.1)Clonage d'objets : analyse approfondieGénérateurs et Itérateurs13Patrons de conception Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode ModèlePatron ÉtatPatron CompositePatron Repository2Espaces de noms et Autoloading
Introduction aux espaces de nomsLe mot-clé useStandard d'Autoloading PSR-4L'Autoloader ComposerRécapitulatif - Projet organisé5Interfaces et Contrats
Introduction aux InterfacesImplémentation d'InterfacesImplémentation d'Interfaces MultiplesInterface vs Classe AbstraiteType Hinting avec les InterfacesRécapitulatif - Calculateur de Formes8Méthodes magiques
Introduction aux méthodes magiques__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Clonage d'objets__serialize & __unserializeRécapitulatif - Collection personnalisée3Propriétés de classe
Propriétés d'instance vs Propriétés statiquesConstantes dans les classesMéthodes et propriétés statiquesPropriétés privées et protégéesPropriétés readonly (PHP 8.1)Récapitulatif - Gestionnaire de compte bancaire6Polymorphisme
Retour sur la redéfinition de méthodePolymorphisme via les interfacesType Hinting et Types d'unionLiaison statique tardiveRécapitulatif - Processeur de paiement9Traits
Introduction aux TraitsUtilisation de plusieurs TraitsRésolution des conflits de TraitsMéthodes abstraites dans les TraitsTraits vs Héritage12Patrons de conception Partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FabriquePatron ObservateurPatron Stratégie