Menu
Coddy logo textTech

Modello Repository

Fa parte della sezione Programmazione orientata agli oggetti del percorso PHP di Coddy. Lezione 81 di 91.

Il Repository Pattern è un pattern di progettazione che funge da intermediario tra la logica di business della tua applicazione e l'archiviazione dei dati. Fornisce un'interfaccia simile a una collezione per accedere agli oggetti di dominio, nascondendo i dettagli di come i dati vengono effettivamente archiviati o recuperati.

Pensa a un repository come a una raccolta specializzata che sa come rendere persistenti e recuperare gli oggetti. Il codice della tua applicazione chiede al repository un utente tramite ID o salva un nuovo prodotto, senza sapere se i dati risiedono in un database, in un file o in un'API. Questa separazione rende il tuo codice più facile da testare e più flessibile.

<?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'implementazione del repository gestisce il meccanismo di archiviazione effettivo:

<?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());

Output:

Alice
2

Il bello di questo pattern è che puoi sostituire le implementazioni senza modificare la logica di business. Devi passare dall'archiviazione in memoria a un database? Crea una nuova classe repository che implementi la stessa interfaccia. Il codice della tua applicazione rimane intatto perché dipende dall'interfaccia, non dall'implementazione concreta.

challenge icon

Sfida

Facile

Costruiamo un sistema di inventario dei prodotti usando il Repository Pattern. Creerai una netta separazione tra gli oggetti del dominio e il modo in cui vengono archiviati, così il codice della tua applicazione potrà lavorare con i prodotti senza conoscere i dettagli dell’archiviazione.

Organizzerai il codice in quattro file:

  • Product.php: Crea una classe Product che rappresenti gli articoli del tuo inventario. Ogni prodotto ha un id (int), un name (string) e un price (float). Usa la promozione dei parametri del costruttore con proprietà pubbliche per facilitare l’accesso.
  • ProductRepositoryInterface.php: Definisci un’interfaccia ProductRepositoryInterface che stabilisca il contratto per qualsiasi implementazione dell’archiviazione dei prodotti. La tua interfaccia dovrebbe dichiarare questi metodi:
    • find(int $id): ?Product: Recupera un prodotto tramite ID, oppure null se non viene trovato
    • findAll(): array: Ottieni tutti i prodotti come array
    • save(Product $product): void: Archivia o aggiorna un prodotto
    • delete(int $id): void: Rimuovi un prodotto tramite ID
  • InMemoryProductRepository.php: Includi sia la classe Product sia l’interfaccia. Crea una classe InMemoryProductRepository che implementi l’interfaccia usando un array privato per archiviare i prodotti. I prodotti dovrebbero essere indicizzati tramite il loro ID per consentire ricerche efficienti. Il metodo findAll() dovrebbe restituire solo gli oggetti prodotto (usa array_values() per reimpostare le chiavi dell’array).
  • main.php: Includi il file del repository. Riceverai due input: prima una stringa JSON con i prodotti da aggiungere, poi, su una riga separata, l’ID intero da cercare.

    Il formato JSON sarà:

    [{"id": 1, "name": "Laptop", "price": 999.99}, {"id": 2, "name": "Mouse", "price": 29.99}]

    Crea un InMemoryProductRepository, salva tutti i prodotti dall’input JSON, poi usa il secondo input (l’ID) per trovare un prodotto specifico. Stampa i risultati in questo formato:

    Total products: [count]
    Found: [name] - $[price]

    Formatta il prezzo con due cifre decimali. Se il prodotto non viene trovato, stampa Found: Not found.

Il Repository Pattern è particolarmente utile quando devi sostituire le implementazioni di archiviazione. Il codice principale dipende solo dall’interfaccia: passare dall’archiviazione in memoria a un database significherebbe creare una nuova classe repository senza modificare alcuna logica dell’applicazione.

Provalo tu

<?php

require_once 'InMemoryProductRepository.php';

// Leggi l'input
$jsonInput = trim(fgets(STDIN));
$searchId = intval(trim(fgets(STDIN)));

// Converti l'input JSON in un array
$productsData = (array)json_decode($jsonInput, true);

// TODO: Crea un'istanza di InMemoryProductRepository

// TODO: Scorri $productsData e salva ogni prodotto
// Ogni elemento ha le chiavi 'id', 'name' e 'price'

// TODO: Ottieni tutti i prodotti e stampa il numero totale
// Formato: "Total products: [count]"

// TODO: Trova il prodotto con $searchId
// Se trovato, stampa: "Found: [name] - $[price]" (con il prezzo formattato a 2 cifre decimali)
// Se non trovato, stampa: "Found: Not found"

?>
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore PHP online