Patron Dépôt
Fait partie de la section Programmation Orientée Objet du Journey PHP de Coddy. Leçon 81 sur 91.
Le Repository Pattern est un modèle de conception qui sert d’intermédiaire entre la logique métier de votre application et le stockage des données. Il fournit une interface semblable à une collection pour accéder aux objets du domaine, en masquant les détails de la manière dont les données sont réellement stockées ou récupérées.
Considérez un dépôt comme une collection spécialisée qui sait comment persister et récupérer des objets. Le code de votre application demande au dépôt un utilisateur par son ID ou enregistre un nouveau produit, sans savoir si les données se trouvent dans une base de données, un fichier ou une API. Cette séparation rend votre code plus facile à tester et plus flexible.
<?php
interface UserRepositoryInterface {
public function find(int $id): ?User;
public function findAll(): array;
public function save(User $user): void;
public function delete(int $id): void;
}
class User {
public function __construct(
public int $id,
public string $name,
public string $email
) {}
}
L’implémentation du dépôt gère le mécanisme de stockage réel :
<?php
class InMemoryUserRepository implements UserRepositoryInterface {
private array $users = [];
public function find(int $id): ?User {
return $this->users[$id] ?? null;
}
public function findAll(): array {
return array_values($this->users);
}
public function save(User $user): void {
$this->users[$user->id] = $user;
}
public function delete(int $id): void {
unset($this->users[$id]);
}
}
$repo = new InMemoryUserRepository();
$repo->save(new User(1, "Alice", "alice@example.com"));
$repo->save(new User(2, "Bob", "bob@example.com"));
echo $repo->find(1)->name . "\n";
echo count($repo->findAll());
Sortie :
Alice
2L’intérêt de ce modèle est que vous pouvez remplacer les implémentations sans modifier votre logique métier. Vous devez passer d’un stockage en mémoire à une base de données ? Créez une nouvelle classe de dépôt qui implémente la même interface. Le code de votre application reste intact, car il dépend de l’interface, et non de l’implémentation concrète.
Défi
FacileConstruisons un système d’inventaire de produits à l’aide du modèle Repository. Vous créerez une séparation claire entre vos objets de domaine et la manière dont ils sont stockés, ce qui permettra au code de votre application de travailler avec des produits sans connaître les détails du stockage.
Vous organiserez votre code sur quatre fichiers :
Product.php: créez une classeProductreprésentant les articles de votre inventaire. Chaque produit possède unid(int), unname(string) et unprice(float). Utilisez la promotion des propriétés du constructeur avec des propriétés publiques pour faciliter l’accès.ProductRepositoryInterface.php: définissez une interfaceProductRepositoryInterfacequi établit le contrat pour toute implémentation de stockage de produits. Votre interface doit déclarer les méthodes suivantes :find(int $id): ?Product: récupère un produit par son ID, ou null s’il est introuvablefindAll(): array: récupère tous les produits sous forme de tableausave(Product $product): void: enregistre ou met à jour un produitdelete(int $id): void: supprime un produit par son ID
InMemoryProductRepository.php: incluez à la fois la classe Product et l’interface. Créez une classeInMemoryProductRepositoryqui implémente l’interface en utilisant un tableau privé pour stocker les produits. Les produits doivent être indexés par leur ID pour permettre une recherche efficace. La méthodefindAll()doit retourner uniquement les objets produits (utilisezarray_values()pour réinitialiser les clés du tableau).main.php: incluez le fichier du dépôt. Vous recevrez deux entrées : d’abord une chaîne JSON contenant les produits à ajouter, puis, sur une ligne distincte, l’ID entier à rechercher.Le format JSON sera le suivant :
[{"id": 1, "name": "Laptop", "price": 999.99}, {"id": 2, "name": "Mouse", "price": 29.99}]Créez un
InMemoryProductRepository, enregistrez tous les produits provenant de l’entrée JSON, puis utilisez la deuxième entrée (l’ID) pour trouver un produit spécifique. Affichez les résultats dans ce format :Total products: [count] Found: [name] - $[price]Formatez le prix avec deux décimales. Si le produit est introuvable, affichez plutôt
Found: Not found.
Le modèle Repository est particulièrement utile lorsque vous devez remplacer des implémentations de stockage. Votre code principal dépend uniquement de l’interface : passer d’un stockage en mémoire à une base de données consisterait à créer une nouvelle classe de dépôt sans modifier la logique de l’application.
Essayez vous-même
<?php
require_once 'InMemoryProductRepository.php';
// Lire l'entrée
$jsonInput = trim(fgets(STDIN));
$searchId = intval(trim(fgets(STDIN)));
// Analyser l'entrée JSON en un tableau
$productsData = (array)json_decode($jsonInput, true);
// TODO: Créer une instance de InMemoryProductRepository
// TODO: Parcourir $productsData et enregistrer chaque produit
// Chaque élément a les clés 'id', 'name' et 'price'
// TODO: Récupérer tous les produits et afficher le nombre total
// Format: "Total products: [count]"
// TODO: Trouver le produit avec $searchId
// Si trouvé, afficher : "Found: [name] - $[price]" (prix formaté à 2 décimales)
// If not found, print: "Found: Not found"
?>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
1Fondamentaux de la POO
Fichiers externesIntroduction à la POOClasses et objetsLe mot-clé $thisMéthodesPropriétésConstructeur (__construct)Destructeur (__destruct)Récapitulatif - Calculatrice simple4Héritage
Héritage de baseLe mot-clé parent::Redéfinition des méthodesLe mot-clé finalClasses abstraitesRécapitulatif – Hiérarchie des employés7Encapsulation
Public, Protected, PrivateModificateurs d’accès en profondeurAccesseurs et mutateursDissimulation de l’informationPromotion des constructeurs (8.0)Récapitulatif – Système de fiches étudiant10Concepts avancés de la POO
Composition ou héritageInjection de dépendancesClasses anonymesÉnumérations (PHP 8.1)Fibres (PHP 8.1)Approfondissement du clonage d’objetsGénérateurs et itérateurs13Patrons de conception – Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode modèlePatron ÉtatPatron CompositePatron Dépôt2Espaces de noms et chargement automatique
Introduction aux espaces de nomsLe mot-clé useNorme de chargement automatique PSR-4Autoloader de ComposerRécapitulatif - Projet organisé5Interfaces et contrats
Introduction aux interfacesImplémentation des interfacesImplémentation de plusieurs interfacesInterface ou classe abstraiteIndication de type avec les interfacesRécapitulatif - Calculateur de formes8Méthodes magiques
Introduction aux méthodes magiques__toString et __debugInfo__get, __set, __isset, __unset__call et __callStatic__clone et clonage d’objets__serialize et __unserializeRécapitulatif - Collection personnalisée3Propriétés de classe
Propriétés d’instance vs statiquesConstantes dans les classesMéthodes et propriétés statiquesPropriétés privées et protégéesPropriétés en lecture seule (PHP 8.1)Récapitulatif - Gestionnaire de comptes bancaires6Polymorphisme
Révision de la redéfinition des méthodesPolymorphisme via les interfacesAnnotations de type et types unionLiaison statique tardiveRécapitulatif - Processeur de paiements9Traits
Introduction aux traitsUtilisation de plusieurs traitsRésolution des conflits entre traitsMéthodes abstraites dans les traitsTraits par rapport à l’héritage12Patrons de conception – Partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FactoryPatron ObserverPatron StrategyEntraînez-vous par vous-même : Compilateur PHP en ligne