Menu
Coddy logo textTech

Repository Kalıbı

Coddy'nin PHP Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 81 / 91.

Repository Deseni, uygulamanızın iş mantığı ile veri depolama katmanı arasında aracılık eden bir tasarım desenidir. Verilerin gerçekte nasıl saklandığı veya getirildiğiyle ilgili ayrıntıları gizleyerek, domain nesnelerine erişmek için koleksiyon benzeri bir arayüz sağlar.

Bir repository'yi, nesneleri nasıl kalıcı hale getireceğini ve geri getireceğini bilen özelleşmiş bir koleksiyon olarak düşünün. Uygulama kodunuz, verilerin bir veritabanında mı, dosyada mı yoksa bir API'de mi olduğunu bilmeden, repository'den ID'ye göre bir kullanıcı ister veya yeni bir ürünü kaydeder. Bu ayrım, kodunuzu daha test edilebilir ve esnek hale getirir.

<?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
    ) {}
}

Repository uygulaması, gerçek depolama mekanizmasını yönetir:

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

Çıktı:

Alice
2

Bu desenin güzelliği, iş mantığınızı değiştirmeden uygulamaları (implementations) değiştirebilmenizdir. Bellek içi depolamadan bir veritabanına geçmeniz mi gerekiyor? Aynı arayüzü (interface) uygulayan yeni bir repository sınıfı oluşturun. Uygulama kodunuz dokunulmadan kalır çünkü somut uygulamaya (concrete implementation) değil, arayüze (interface) bağlıdır.

challenge icon

Görev

Kolay

Repository Pattern kullanarak bir ürün envanter sistemi oluşturalım. Alan (domain) nesneleriniz ile bunların nasıl saklandığı arasında temiz bir ayrım oluşturacaksınız; bu da uygulama kodunuzun saklama detaylarını bilmeden ürünlerle çalışmasına olanak tanır.

Kodunuzu dört dosya halinde düzenleyeceksiniz:

  • Product.php — Envanterinizdeki öğeleri temsil eden bir Product sınıfı oluşturun. Her ürünün bir id (int), name (string) ve price (float) değeri vardır. Kolay erişim için genel (public) özelliklerle birlikte constructor promotion kullanın.
  • ProductRepositoryInterface.php — Herhangi bir ürün saklama uygulaması için sözleşmeyi belirleyen bir ProductRepositoryInterface tanımlayın. Arayüzünüz şu yöntemleri bildirmelidir:
    • find(int $id): ?Product — Bir ürünü ID'ye göre getirir veya bulunamazsa null döner
    • findAll(): array — Tüm ürünleri bir dizi olarak getirir
    • save(Product $product): void — Bir ürünü saklar veya günceller
    • delete(int $id): void — Bir ürünü ID'ye göre siler
  • InMemoryProductRepository.php — Hem Product sınıfını hem de arayüzü dahil edin. Ürünleri saklamak için özel (private) bir dizi kullanan ve arayüzü uygulayan bir InMemoryProductRepository sınıfı oluşturun. Ürünler, verimli arama için ID'lerine göre dizinlenmelidir. findAll() yöntemi yalnızca ürün nesnelerini döndürmelidir (dizi anahtarlarını sıfırlamak için array_values() kullanın).
  • main.php — Repository dosyasını dahil edin. İki girdi alacaksınız: önce eklenecek ürünlerin JSON dizesi, ardından ayrı bir satırda aranacak tam sayı ID.

    JSON formatı şu şekilde olacaktır:

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

    Bir InMemoryProductRepository oluşturun, JSON girdisindeki tüm ürünleri kaydedin, ardından belirli bir ürünü bulmak için ikinci girdiyi (ID) kullanın. Sonuçları şu formatta yazdırın:

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

    Fiyatı iki ondalık basamak olacak şekilde biçimlendirin. Ürün bulunamazsa, bunun yerine Found: Not found yazdırın.

Repository Pattern, saklama uygulamalarını değiştirmeniz gerektiğinde parlar. Ana kodunuz yalnızca arayüzüne bağlıdır — bellek içi saklamadan bir veritabanına geçmek, herhangi bir uygulama mantığını değiştirmeden yeni bir repository sınıfı oluşturmak anlamına gelir.

Kendin dene

<?php

require_once 'InMemoryProductRepository.php';

// Girdiyi oku
$jsonInput = trim(fgets(STDIN));
$searchId = intval(trim(fgets(STDIN)));

// JSON girdisini bir diziye dönüştür
$productsData = (array)json_decode($jsonInput, true);

// TODO: Bir InMemoryProductRepository örneği oluştur

// TODO: $productsData üzerinde döngü kur ve her ürünü kaydet
// Her öğe 'id', 'name' ve 'price' anahtarlarına sahiptir

// TODO: Tüm ürünleri al ve toplam sayıyı yazdır
// Format: "Total products: [count]"

// TODO: $searchId ile ürünü bul
// Eğer bulunursa, yazdır: "Found: [name] - $[price]" (fiyat 2 ondalık basamaklı formatta)
// Eğer bulunamazsa, yazdır: "Found: Not found"

?>
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler