İçeriğe geç
academia.sh

Ders 08 / 21

Form ve Doğrulama

Kural dizgeleriyle çalışan bir doğrulayıcı kurulur; geçersiz girdide kayıt adımının atlandığı, geçerli girdide koştuğu ve ilk hatada durmanın sonraki kuralı atladığı ölçülür.

Yayın Güncelleme

Bu derste

  • Kural dizgelerini çözen bir doğrulayıcı ve hata iletisi üreten bir form eylemi kurmak
  • Geçersiz girdide kayıt adımının atlandığını, 422 durumuyla birlikte ölçmek
  • Geçerli girdide kayıt adımının koştuğunu karşıt ölçüm olarak göstermek
  • İlk hatada durmanın sonraki kuralı atlamasını ve kullanıcıya giden ileti sayısına etkisini okumak
İçindekiler

Şablon önüne konan her değeri basar; değerin yazılması gereken biçimde olup olmadığına bakmaz. O kontrol formun eyleminde yapılır: kullanıcıdan gelen girdi kurala uymazsa kayıt adımına ulaşmamalıdır. Peki ulaşmadığını nereden bilirsiniz? Bu derste soru, kuralın tutmadığı istekte kayıt adımının ne olduğudur.

Ölçü ekseni önceki dersteki gibi, beklenen parça bu istekte koştu mu sorusudur. Karar sırası sinifla() fonksiyonunun kendisidir: koştu, ertelendi, atlandı, bağlanmadı. Bu dersin ağırlıklı sınıfı atlandı‘dır: kayıt adımı eylemin yoluna konmuştur, ama çağrılmaz. Atlanan adım istemciye bir durum koduyla görünür; burada bu kod 422’dir.

GV4. Form girdisi, istek gövdesinden çözülmüş bir dizidir; HTTP katmanı bu derste kurulmaz ve eylem doğrudan bir dizi alır. GV5. Kural dizgesi | ile ayrılmış kurallardan oluşur ve bir kuralın argümanı : ile verilir (en_az:3). GV6. Geçersiz girdi boş ('') ya da kısa ('ab') bir alanla gösterilir; kuralların mantığı özel karakterlerden bağımsızdır. GV7. Hata iletileri ASCII yazılır ki sütun genişliği bozulmasın.

Ö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ı',
    };
}

Doğrulayıcıyı Kurmak

Doğrulayıcı (validation) alan başına kural dizgesini ayrıştırır, her kuralı sırayla çalıştırır ve başarısız olanlar için bir ileti toplar. İki ayrıntı ölçüme bağlıdır. Birincisi, bir alanın bütün kuralları kural çalışmadan önce yola konur; bu yüzden çalışmayan kural atlandı sınıfına düşebilir. İkincisi, kurucudaki seçenek ilk hatada durmayı belirler: durursa aynı alanın sonraki kuralları çağrılmaz.

Form eylemi doğrulayıcıyı çağırır. Girdi geçerli değilse 422 döner, hata iletileri ve eski girdi yanıta konur; eski girdi, formun yeniden gösterilirken alanların boşalmamasını sağlar. Geçerliyse kayıt adımı koşar ve 201 döner. Kayıt adımı eylemin yoluna eylem başlarken konur, çağrısı da yalnızca doğrulama geçtikten sonra yapılır.

<?php
// dogrulama.php — kural dizgeleriyle doğrulayıcı ve yazı kaydeden eylem
declare(strict_types=1);
require_once 'kostu.php';

final class Dogrulayici {
    public array $hatalar = [];

    public function __construct(private bool $ilkHatadaDur = true) {}

    public function dogrula(array $girdi, array $kurallar): bool {
        $this->hatalar = [];
        foreach ($kurallar as $alan => $dizge) {
            $liste = explode('|', $dizge);
            foreach ($liste as $kural) {
                Gunluk::yola("kural:$alan:" . explode(':', $kural)[0]);
            }
            foreach ($liste as $kural) {
                if ($this->ilkHatadaDur && isset($this->hatalar[$alan])) break;
                [$ad, $arguman] = array_pad(explode(':', $kural, 2), 2, null);
                Gunluk::kostu("kural:$alan:$ad");
                $deger = (string) ($girdi[$alan] ?? '');
                $gecti = match ($ad) {
                    'zorunlu' => $deger !== '',
                    'en_az' => mb_strlen($deger) >= (int) $arguman,
                };
                if (!$gecti) {
                    $this->hatalar[$alan][] = match ($ad) {
                        'zorunlu' => "$alan zorunludur",
                        'en_az' => "$alan en az $arguman karakter olmalidir",
                    };
                }
            }
        }
        return $this->hatalar === [];
    }
}

function yaziKaydet(array $girdi, Dogrulayici $dogrulayici, array $kurallar): array {
    Gunluk::yola('kayit');
    if (!$dogrulayici->dogrula($girdi, $kurallar)) {
        return [422, ['hatalar' => $dogrulayici->hatalar, 'eski' => $girdi]];
    }
    Gunluk::kostu('kayit');
    return [201, ['kaydedilen' => $girdi['baslik']]];
}

function yanitYaz(array $yanit): void {
    [$durum, $govde] = $yanit;
    echo "durum $durum\n";
    foreach ($govde['hatalar'] ?? [] as $alan => $iletiler) {
        foreach ($iletiler as $ileti) echo "  hata $alan: $ileti\n";
    }
    foreach ($govde['eski'] ?? [] as $alan => $deger) echo "  eski $alan='$deger'\n";
    if (isset($govde['kaydedilen'])) echo "  kaydedilen {$govde['kaydedilen']}\n";
}

Geçersiz Girdide Kayıt Adımı

Ölçüm boş bir başlıkla ve iki harfli bir özetle eylemi çağırır. Kurallar: başlık zorunlu, özet en az üç karakter. Beklenen: durum 422, iki hata iletisi, eski girdi yanıtta, kayıt adımı atlandı. Kural parçaları ise ikisi de koştu, çünkü ikisi de çalıştı ve ikisi de tutmadı.

<?php
// gecersiz.php — geçersiz girdide kayıt adımı atlanır
require_once 'dogrulama.php';

$kurallar = ['baslik' => 'zorunlu', 'ozet' => 'en_az:3'];
Gunluk::yeniIstek();
yanitYaz(yaziKaydet(['baslik' => '', 'ozet' => 'ab'], new Dogrulayici(), $kurallar));
foreach (['kural:baslik:zorunlu', 'kural:ozet:en_az', 'kayit'] as $parca) {
    printf("  %-22s %s\n", $parca, sinifla($parca));
}
durum 422
  hata baslik: baslik zorunludur
  hata ozet: ozet en az 3 karakter olmalidir
  eski baslik=''
  eski ozet='ab'
  kural:baslik:zorunlu   koştu
  kural:ozet:en_az       koştu
  kayit                  atlandı

İki hata iletisi gittiği hâlde kayıt adımı atlandı: eylemin yoluna konmuştu, çağrılmadı. Bu atlama sessiz değildir; istemci 422 alır ve hangi alanın neden tutmadığını görür. Kural koştu ile tutmadı farklı şeylerdir: ölçü eksenimiz kuralın çalışıp çalışmadığıdır, geçip geçmediği değil. Hata iletisi kuralın çalışmasının sonucudur.

Karşıt Ölçüm: Geçerli Girdi

Aynı eylem geçerli bir girdiyle çağrılır. Beklenen: durum 201, hata yok, kayıt adımı koştu.

<?php
// gecerli.php — geçerli girdide kayıt adımı koşar
require_once 'dogrulama.php';

$kurallar = ['baslik' => 'zorunlu', 'ozet' => 'en_az:3'];
Gunluk::yeniIstek();
yanitYaz(yaziKaydet(['baslik' => 'Ilk yazi', 'ozet' => 'abc'], new Dogrulayici(), $kurallar));
foreach (['kural:baslik:zorunlu', 'kural:ozet:en_az', 'kayit'] as $parca) {
    printf("  %-22s %s\n", $parca, sinifla($parca));
}
durum 201
  kaydedilen Ilk yazi
  kural:baslik:zorunlu   koştu
  kural:ozet:en_az       koştu
  kayit                  koştu

Doğrulamanın kendisi iki istekte de aynı biçimde koştu; yalnızca ardındaki adımın kaderi değişti. Kayıt adımı doğrulamadan bağımsız bir kapı değildir, doğrulamanın sonucuna bağlı bir dallanmadır.

Sınırlayıcı Ölçüm

Doğrulayıcı kurucusundaki seçenek, aynı girdide kullanıcıya kaç ileti gideceğini belirler. Özet alanı iki kurala sahip olsun (zorunlu|en_az:3) ve girdi boş olsun. İlk hatada durmayan doğrulayıcıda iki kural da çalışır ve iki ileti toplanır. İlk hatada duran doğrulayıcıda zorunlu tutmaz, en_az çağrılmaz ve tek ileti toplanır.

<?php
// durma.php — ilk hatada durmak sonraki kuralı atlatır
require_once 'dogrulama.php';

$kurallar = ['baslik' => 'zorunlu', 'ozet' => 'zorunlu|en_az:3'];
foreach ([true, false] as $dur) {
    Gunluk::yeniIstek();
    echo $dur ? "ilk hatada durur\n" : "durmaz\n";
    yanitYaz(yaziKaydet(['baslik' => 'Ilk yazi', 'ozet' => ''], new Dogrulayici($dur), $kurallar));
    foreach (['kural:ozet:zorunlu', 'kural:ozet:en_az', 'kayit'] as $parca) {
        printf("  %-22s %s\n", $parca, sinifla($parca));
    }
}
ilk hatada durur
durum 422
  hata ozet: ozet zorunludur
  eski baslik='Ilk yazi'
  eski ozet=''
  kural:ozet:zorunlu     koştu
  kural:ozet:en_az       atlandı
  kayit                  atlandı
durmaz
durum 422
  hata ozet: ozet zorunludur
  hata ozet: ozet en az 3 karakter olmalidir
  eski baslik='Ilk yazi'
  eski ozet=''
  kural:ozet:zorunlu     koştu
  kural:ozet:en_az       koştu
  kayit                  atlandı

Duran doğrulayıcıda en_az kuralı atlandı, durmayanda koştu; yanıtın durumu iki durumda da 422 ve kayıt iki durumda da atlandı. Kayıt adımının kaderini kuralların tutup tutmaması belirler, ileti sayısını ise duruş seçimi. Boş bir alana ayrıca “en az üç karakter” demek kullanıcıya yeni bilgi vermez; bu yüzden ilk hatada durmak sık seçilir. Ama bir alanın bütün sorunlarını tek turda göstermek isteyen form, ikinci seçeneği kurar. Seçim bir tasarım kararıdır ve yanıtta görünür.

Özet

  • Doğrulayıcı kural dizgelerini çözer, hata iletilerini toplar ve eski girdiyi forma geri döndürür.
  • Bu dersin ölçü sınıfı atlandı’dır: geçersiz girdide kayıt adımı eylemin yoluna konmuş olduğu hâlde çağrılmadı; istemci 422 ve iletiler aldı.
  • Karşıt ölçümde geçerli girdi kayıt adımını koştu sınıfına getirdi ve durum 201 oldu.
  • Kuralın çalışması (koştu) kuralın geçmesinden ayrıdır; tutmayan kural da koşmuştur.
  • İlk hatada durmak aynı alandaki sonraki kuralı atlandı yapar ve kullanıcıya giden ileti sayısını azaltır; kayıt adımının kaderi değişmez.

Sonraki Adım

Geçerli girdi kayıt adımına ulaştı. Kayıt bir modelin içinden geçtiğinde, kaydedilirken başka neler çalışır? Bir sonraki ders nesne ve tablo bağlamasını ele alır ve model kaydedilirken hangi parçanın koştuğunu ölçer.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ ↵ Esc gezin · aç · kapat