Depo 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 alanı arasında aracılık eden bir tasarım kalıbıdır. Etki alanı nesnelerine erişim için koleksiyon benzeri bir arayüz sağlar ve verilerin gerçekte nasıl depolandığı veya alındığına ilişkin ayrıntıları gizler.
Bir repository’yi, nesneleri kalıcı olarak saklamayı ve geri almayı bilen özel bir koleksiyon olarak düşün. Uygulama kodun, verilerin bir veritabanında, dosyada veya API’de bulunup bulunmadığını bilmeden repository’den ID’ye göre bir kullanıcı ister ya da yeni bir ürün kaydeder. Bu ayrım, kodunu daha kolay test edilebilir ve esnek hâle 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
) {}
}
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
2Bu kalıbın güzelliği, iş mantığınızı değiştirmeden uygulamaları değiştirebilmenizdir. Bellek içi depolamadan veritabanına geçmeniz mi gerekiyor? Aynı arayüzü uygulayan yeni bir repository sınıfı oluşturun. Uygulama kodunuz, somut uygulamaya değil arayüze bağlı olduğu için olduğu gibi kalır.
Görev
KolayRepository Pattern'ı kullanarak bir ürün envanter sistemi oluşturalım. Alan nesneleriniz ile bunların nasıl depolandığı arasında temiz bir ayrım oluşturacak ve uygulama kodunuzun depolama ayrıntılarını bilmeden ürünlerle çalışmasına olanak tanıyacaksınız.
Kodunuzu dört dosya arasında düzenleyeceksiniz:
Product.php: Envanterinizdeki öğeleri temsil eden birProductsınıfı oluşturun. Her ürünün birid(int),name(string) veprice(float) değeri vardır. Kolay erişim için public özelliklerle birlikte constructor promotion kullanın.ProductRepositoryInterface.php: Herhangi bir ürün depolama uygulaması için sözleşmeyi tanımlayan birProductRepositoryInterfaceoluşturun. Arayüzünüz şu metotları bildirmelidir:find(int $id): ?Product: Bir ürünü ID'sine göre alın veya bulunamazsa null döndürünfindAll(): array: Tüm ürünleri bir dizi olarak alınsave(Product $product): void: Bir ürünü depolayın veya güncelleyindelete(int $id): void: Bir ürünü ID'sine göre kaldırın
InMemoryProductRepository.php: Hem Product sınıfını hem de arayüzü dahil edin. Ürünleri depolamak için private bir dizi kullanarak arayüzü uygulayan birInMemoryProductRepositorysınıfı oluşturun. Verimli arama için ürünler ID'lerine göre indekslenmelidir.findAll()metodu yalnızca ürün nesnelerini döndürmelidir (dizi anahtarlarını sıfırlamak içinarray_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 tamsayı ID.JSON biçimi şöyle olacaktır:
[{"id": 1, "name": "Laptop", "price": 999.99}, {"id": 2, "name": "Mouse", "price": 29.99}]Bir
InMemoryProductRepositoryoluş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 biçimde yazdırın:Total products: [count] Found: [name] - $[price]Fiyatı iki ondalık basamakla biçimlendirin. Ürün bulunamazsa bunun yerine
Found: Not foundyazdırın.
Repository Pattern, depolama uygulamalarını değiştirmeniz gerektiğinde öne çıkar. Ana kodunuz yalnızca arayüze bağlıdır: bellek içi depolamadan 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 ayrıştır
$productsData = (array)json_decode($jsonInput, true);
// TODO: Bir InMemoryProductRepository örneği oluştur
// TODO: $productsData üzerinde döngü yap ve her ürünü kaydet
// Her öğenin 'id', 'name' ve 'price' anahtarları vardır
// TODO: Tüm ürünleri al ve toplam sayıyı yazdır
// Format: "Total products: [count]"
// TODO: $searchId ile ürünü bul
// Bulunursa yazdır: "Found: [name] - $[price]" (fiyat 2 ondalık basamağa biçimlendirilmiş)
// If not found, print: "Found: Not found"
?>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
1OOP Temelleri
Harici DosyalarOOP'ye GirişSınıflar ve Nesneler$this Anahtar SözcüğüMetotlarÖzelliklerYapıcı (__construct)Yıkıcı (__destruct)Tekrar - Basit Hesap Makinesi4Kalıtım
Temel Kalıtımparent:: Anahtar SözcüğüMetot Geçersiz Kılmafinal Anahtar SözcüğüSoyut SınıflarTekrar - Çalışan Hiyerarşisi7Kapsülleme
Public, Protected, PrivateErişim Belirleyicileri DerinlemesineGetter ve Setter'larBilgi GizlemeYapıcı Özellik Terfisi (8.0)Tekrar - Öğrenci Kayıt Sistemi10İleri Düzey OOP Kavramları
Composition ve KalıtımBağımlılık EnjeksiyonuAnonim SınıflarEnum'lar (PHP 8.1)Fiber'lar (PHP 8.1)Nesne Klonlamaya Derinlemesine BakışÜreteçler ve Yineleyiciler13Tasarım Kalıpları Bölüm 2
Komut KalıbıAdaptör KalıbıDekoratör KalıbıŞablon Metot KalıbıDurum KalıbıBileşik KalıpDepo Kalıbı2Namespace’ler ve Autoloading
Namespace’lere Girişuse Anahtar SözcüğüPSR-4 Autoloading StandardıComposer AutoloaderTekrar - Düzenli Proje5Arayüzler ve Sözleşmeler
Arayüzlere GirişArayüzleri UygulamaBirden Çok Arayüz UygulamaArayüz ve Soyut Sınıf KarşılaştırmasıArayüzlerle Tür İpuçlarıTekrar - Şekil Hesaplayıcı8Sihirli Metotlar
Sihirli Metotlara Giriş__toString ve __debugInfo__get, __set, __isset, __unset__call ve __callStatic__clone ve Nesne Klonlama__serialize ve __unserializeTekrar - Özel Koleksiyon3Sınıf Özellikleri
Örnek ve Statik ÖzelliklerSınıflarda SabitlerStatik Metotlar ve ÖzelliklerPrivate ve Protected ÖzelliklerSalt Okunur Özellikler (PHP 8.1)Tekrar - Banka Hesabı Yöneticisi6Çok Biçimlilik
Metot Geçersiz Kılmayı Yeniden Ele AlmaArayüzler Yoluyla Çok BiçimlilikTür İpuçları ve Birleşim TürleriGeç Bağlanan Statik ÇağrılarÖzet - Ödeme İşlemcisi9Trait'ler
Trait'lere GirişBirden Çok Trait KullanımıTrait Çakışmalarını ÇözümlemeTrait'lerde Soyut MetotlarTrait'ler ve Kalıtım Karşılaştırması12Tasarım Desenleri 1. Bölüm
Tasarım Desenlerine GirişSingleton DeseniFactory DeseniObserver DeseniStrategy DeseniKendi başına pratik yap: Online PHP derleyicisi