Ders 12 / 21
Sayfalama ve Kaynak Dönüşümü
Atlama tabanlı sayfalama ve modelden yanıt dizisine kaynak dönüşümü kurulur; modele eklenen yeni kolonun dönüşüm tanımında olmadığı için yanıta bağlanmadığı, tanıma eklenince koştuğu ve sayfa sınırı dışındaki isteğin boş liste döndürdüğü ölçülür.
Yayın Güncelleme
Bu derste
- Atlama tabanlı sayfalama ve toplam, sayfa, son sayfa bilgisini kurmak
- Modelden yanıt dizisine giden bir kaynak dönüşümü ve koleksiyon kaynağı yazmak
- Modele eklenen yeni kolonun dönüşüm tanımında olmadığı sürece yanıta bağlanmadığını ölçmek
- Sayfa sınırı dışındaki isteğin sonucunu gerçek çıktıyla okumak
İçindekiler
Göç yeni kolonu şemaya ekledi. Peki o kolon API yanıtına kendiliğinden ulaşır mı? Model kolonu bilir, yanıt ise başka bir yerde, bir dönüşüm tanımında kurulur. İkisi arasındaki bağ kendiliğinden kurulmuyorsa, kolon eklendiği hâlde yanıtta hiç görünmeyebilir.
Bu dersin ölçü ekseni, bir kolonun ya da adımın bu yanıtta koştu mu sorusudur. Karar sırası sinifla() fonksiyonunun kendisidir: koştu, ertelendi, atlandı, bağlanmadı. Ağırlıklı sınıf bağlanmadı’dır ve çekirdek derste olduğu gibi en tehlikelisidir: atlanan adım bir durum koduyla, ertelenen adım işçide görünür; bağlanmayan adım hiçbir yerde görünmez ve yanıt 200 döner.
GV20. Tablo, yirmi beş satırlık bir PHP dizisidir ve satırlar id, baslik, ozet ile sonradan eklenmiş okuma_suresi kolonunu taşır; okuma_suresi nötr bir sayıdır. GV21. Sayfalama atlama tabanlıdır (offset): sayfa numarası bir’den başlar ve atlanan satır sayısı (sayfa - 1) * boy olur. GV22. Yanıt durumu, eylemin küçük bir dilimiyle [durum, gövde] çifti olarak döner; HTTP katmanı kurulmaz. GV23. Kaynak dönüşümü, tanımdaki her alanı sırayla modelden alır.
Ölçüm düzeneği değişmeden gelir.
<?php // kostu.php — beklenen bir parça bu istekte koştu mu? declare(strict_types=1); final class Gunluk { public static array $yol = []; // isteğin yoluna konan parçalar public static array $kostu = []; // istek içinde çağrılanlar public static array $ertelenen = []; // isteğin dışına bırakılanlar public static function yeniIstek(): void { self::$yol = self::$kostu = self::$ertelenen = []; } public static function yola(string $parca): void { self::$yol[] = $parca; } public static function kostu(string $parca): void { self::$kostu[] = $parca; } public static function ertele(string $parca): void { self::$ertelenen[] = $parca; } } function sinifla(string $parca): string { return match (true) { in_array($parca, Gunluk::$kostu, true) => 'koştu', in_array($parca, Gunluk::$ertelenen, true) => 'ertelendi', in_array($parca, Gunluk::$yol, true) => 'atlandı', default => 'bağlanmadı', }; }
Sayfalama ve Kaynak
Sayfalama (pagination) uzun bir listeyi sayfalara böler. Atlama tabanlı sayfalama sayfa numarası ve sayfa boyunu alır, öncesindeki satırları atlar ve sayfa boyu kadarını döndürür; toplam satır sayısı ve son sayfa numarası yanıta konur ki istemci kaç sayfa olduğunu bilsin. Kaynak dönüşümü (resource transformation) modelin satırını yanıt dizisine çeviren katmandır. Koleksiyon kaynağı bu dönüşümü bir sayfadaki her satıra uygular ve sayfa bilgisini üst veri (meta) olarak ekler.
Dönüşüm tanımı, hangi alanların yanıta gireceğini adlandırır. Modelde olup tanımda olmayan alan ne yanıta girer ne bir hata üretir. Bu, kaynak dönüşümünün görevi gereğidir: yanıtın biçimi model değiştiğinde kendiliğinden değişmez, yani dönüşüm modelin değişmesinden yanıtı koruyan bir sözleşmedir. Aynı özellik, yeni kolonu unutmaya da imkân verir.
<?php // sayfalama.php — atlama tabanlı sayfalama ve kaynak dönüşümü declare(strict_types=1); require_once 'kostu.php'; function yazilar(): array { return array_map( fn($i) => ['id' => $i, 'baslik' => "Yazi $i", 'ozet' => "Ozet $i", 'okuma_suresi' => ($i % 5) + 1], range(1, 25) ); } function sayfala(array $satirlar, int $sayfa, int $boy): array { Gunluk::kostu('sayfalama'); $toplam = count($satirlar); return [ 'satirlar' => array_slice($satirlar, ($sayfa - 1) * $boy, $boy), 'sayfa' => $sayfa, 'boy' => $boy, 'toplam' => $toplam, 'son' => (int) ceil($toplam / $boy), ]; } final class Kaynak { public function __construct(private array $alanlar) {} public function donustur(array $satir): array { $cikti = []; foreach ($this->alanlar as $alan) { Gunluk::yola("alan:$alan"); Gunluk::kostu("alan:$alan"); $cikti[$alan] = $satir[$alan]; } return $cikti; } public function koleksiyon(array $sayfa): array { return [ 'veri' => array_map(fn($s) => $this->donustur($s), $sayfa['satirlar']), 'meta' => ['sayfa' => $sayfa['sayfa'], 'boy' => $sayfa['boy'], 'toplam' => $sayfa['toplam'], 'son' => $sayfa['son']], ]; } } function yazilarEylemi(Kaynak $kaynak, int $sayfa, int $boy = 10): array { return [200, $kaynak->koleksiyon(sayfala(yazilar(), $sayfa, $boy))]; } function yanitYaz(array $yanit): void { [$durum, $govde] = $yanit; $m = $govde['meta']; echo "durum $durum\n"; echo " sayfa={$m['sayfa']} boy={$m['boy']} toplam={$m['toplam']} son={$m['son']}\n"; echo " kayit=" . count($govde['veri']) . "\n"; if ($govde['veri'] !== []) echo " anahtarlar=" . implode(',', array_keys($govde['veri'][0])) . "\n"; } function raporla(array $parcalar): void { foreach ($parcalar as $parca) printf(" %-18s %s\n", $parca, sinifla($parca)); }
Yeni Kolon Yanıta Ulaşıyor mu
Tablo okuma_suresi kolonunu taşıyor, ama dönüşüm tanımı yalnızca id, baslik ve ozet alanlarını adlandırıyor. Ölçüm ikinci sayfayı ister. Beklenen: durum 200, on kayıt, toplam yirmi beş, son sayfa üç; sayfalama koştu, baslik koştu, okuma_suresi bağlanmadı.
<?php // yenikolon.php — tanımda olmayan kolon yanıta bağlanmaz require_once 'sayfalama.php'; Gunluk::yeniIstek(); yanitYaz(yazilarEylemi(new Kaynak(['id', 'baslik', 'ozet']), 2)); raporla(['sayfalama', 'alan:baslik', 'alan:okuma_suresi']);
durum 200 sayfa=2 boy=10 toplam=25 son=3 kayit=10 anahtarlar=id,baslik,ozet sayfalama koştu alan:baslik koştu alan:okuma_suresi bağlanmadı
Yanıt 200, sayfa bilgisi doğru, anahtarlar üç. okuma_suresi tabloda her satırda var, ama yanıtta yok ve bunun hiçbir izi yok: ne uyarı ne hata. Dönüşüm yeni kolonu bilmediği için kolon ne yola konuldu ne çağrıldı: bağlanmadı. İstemci, kolonun eklendiğini bilmeden eski biçimde yanıt almaya devam eder; kolonu ekleyen geliştirici ise testten yalnızca eski alanların bulunduğunu görür ve geçer.
Karşıt Ölçüm: Tanıma Eklemek
Aynı istek, tanıma okuma_suresi eklenmiş bir kaynakla yapılır. Beklenen: alan koştu ve anahtar sayısı dört.
<?php // tanimli.php — tanıma eklenen kolon yanıta ulaşır require_once 'sayfalama.php'; Gunluk::yeniIstek(); yanitYaz(yazilarEylemi(new Kaynak(['id', 'baslik', 'ozet', 'okuma_suresi']), 2)); raporla(['sayfalama', 'alan:baslik', 'alan:okuma_suresi']);
durum 200 sayfa=2 boy=10 toplam=25 son=3 kayit=10 anahtarlar=id,baslik,ozet,okuma_suresi sayfalama koştu alan:baslik koştu alan:okuma_suresi koştu
Aynı sayfa, aynı sayfa bilgisi; fark yalnızca tanımdadır. Kolon tanıma eklenince koştu. Yanıtın biçimi böylece bilerek değişir: tanımdaki bir satır, yanıt sözleşmesinin bir değişikliğidir ve inceleme sırasında görünür. Model değişikliğinin kendiliğinden yanıtı değiştirmemesi korumadır; maliyeti, bu tanımın elle sürdürülmesidir.
Sınırlayıcı Ölçüm
Sayfa sınırı dışındaki istek boş liste mi döndürür, hata mı? Tablo yirmi beş satır, sayfa boyu on; son sayfa üç. Ölçüm karşılaştırma için üçüncü sayfayı, ardından dördüncü ve doksan dokuzuncu sayfayı ister. Sayfalama array_slice ile yapıldığı için sınır dışı sayfa özel bir kontrol olmadan çalışır.
<?php // sinirdisi.php — sayfa sınırı dışındaki istek require_once 'sayfalama.php'; foreach ([3, 4, 99] as $sayfa) { Gunluk::yeniIstek(); echo "istenen sayfa $sayfa\n"; yanitYaz(yazilarEylemi(new Kaynak(['id', 'baslik', 'ozet']), $sayfa)); raporla(['sayfalama', 'alan:baslik']); }
istenen sayfa 3 durum 200 sayfa=3 boy=10 toplam=25 son=3 kayit=5 anahtarlar=id,baslik,ozet sayfalama koştu alan:baslik koştu istenen sayfa 4 durum 200 sayfa=4 boy=10 toplam=25 son=3 kayit=0 sayfalama koştu alan:baslik bağlanmadı istenen sayfa 99 durum 200 sayfa=99 boy=10 toplam=25 son=3 kayit=0 sayfalama koştu alan:baslik bağlanmadı
Çıktıda sınır dışı sayfa hata değildir: durum 200 ve kayıt sayısı sıfır. Üst veri istenen sayfa numarasını olduğu gibi geri verir, son sayfa üç kalır. Dikkat çeken, sınır dışı sayfada alan:baslik kaydıdır: satır olmadığı için dönüşüm hiç çalışmadı ve alan bağlanmadı sınıfına düştü. Aynı alan üçüncü sayfada koştu. Yani “bu alan yanıtta koştu mu” sorusunun cevabı, yanıtta satır olup olmadığına bağlıdır. İstemci boş bir listeyi “bu sayfada kayıt yok” diye okuyabilir, ama hata ile ayırt edemez; hata istenirse sayfa numarasını son ile karşılaştıran açık bir kontrol gerekir.
Özet
- Atlama tabanlı sayfalama sayfa, sayfa boyu, toplam ve son sayfa bilgisini üretir; kaynak dönüşümü modeli yanıt dizisine çevirir.
- Bu dersin ölçü sınıfı
bağlanmadı’dır: modele eklenen kolon dönüşüm tanımında olmadığı için yanıta ulaşmadı, yanıt 200 döndü ve hiçbir hata görünmedi. - Tanıma eklenen kolon
koştu; yanıt biçiminin değişmesi böylece görünür bir karar olur. - Kaynak dönüşümü, model değişikliğinden yanıtı koruyan bir sözleşmedir; yeni kolonun tanıma elle eklenmesi bu korumanın bedelidir.
- Sayfa sınırı dışındaki istek 200 ve boş liste döndürdü; satır olmadığı için dönüşüm hiç çalışmadı.
Sonraki Adım
Yanıt hazır, ama bu yanıtı kimin istediğine henüz bakmadık. Yetkisi olmayan bir kullanıcı aynı listeyi isterse ne olur? Sıradaki konu olan uygulama hizmetlerinin ilk dersi, Kimlik Doğrulama ve Yetkilendirme, bu soruyu ele alır.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.