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 Pattern, 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, alan (domain) nesnelerine erişmek için koleksiyon benzeri bir arayüz sağlar.

Bir depoyu (repository), nesneleri nasıl kalıcı hale getireceğini ve geri getireceğini bilen özel bir koleksiyon olarak düşünün. Uygulama kodunuz, verilerin bir veritabanında mı, dosyada mı yoksa bir API'de mi olduğunu bilmeden, depodan 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 (depo) 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ı değiştirebilmenizdir. Bellek içi depolamadan bir veritabanına geçmeniz mi gerekiyor? Aynı arayüzü uygulayan yeni bir repository sınıfı oluşturun. Uygulama kodunuz dokunulmadan kalır çünkü somut uygulamaya değil, arayüze bağlıdır.

challenge icon

Görev

Kolay

Repository Desenini 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ıyacaktı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 yapıcı (constructor) tanıtımını 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 kullanarak 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 — Depo (repository) dosyasını dahil edin. Bir girdi alacaksınız: eklenecek ürünlerin dizisini içeren bir JSON dizesi ve ardından aranacak bir 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 Deseni, 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 depo sınıfı oluşturmak anlamına gelir.

Kopya kağıdı

Repository Pattern (Depo Deseni), iş mantığı ile veri depolama arasında aracılık yaparak, depolama uygulama detaylarını gizlerken alan nesnelerine erişmek için koleksiyon benzeri bir arayüz sağlar.

Veri erişimi için sözleşmeyi belirleyen bir repository arayüzü tanımlayın:

<?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;
}

Yapıcı (constructor) tanıtımını kullanarak bir alan (domain) sınıfı oluşturun:

<?php
class User {
    public function __construct(
        public int $id,
        public string $name,
        public string $email
    ) {}
}

Repository arayüzünü somut bir depolama mekanizması ile uygulayın:

<?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]);
    }
}

Repository'yi arayüzü üzerinden kullanın:

$repo = new InMemoryUserRepository();
$repo->save(new User(1, "Alice", "alice@example.com"));
$user = $repo->find(1);
$allUsers = $repo->findAll();

Bu desen, iş mantığını değiştirmeden uygulamaların yer değiştirilmesine olanak tanır — kodunuz somut uygulamaya değil, arayüze bağlıdır.

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şturun

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

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

// TODO: $searchId ile eşleşen ürünü bulun
// Eğer bulunursa, şunu yazdırın: "Found: [name] - $[price]" (fiyat 2 ondalık basamaklı formatta olmalıdır)
// Eğer bulunamazsa, şunu yazdırın: "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