Ders 12 / 14
Form İşleme
Formdan gelen dizgilerin filter_var ile doğrulanması: başarısızlığın dönüş değeriyle duyulması, null'a çevrilmesi ve geçerli 0 değerinin başarısızlıkla karışması.
Yayın Güncelleme
Bu derste
- Geçersiz bir form değerinin hangi kanaldan duyulduğunu ölçerek gösterir
- Bir POST formunu yerleşik sunucuya göndererek doğrulama ve çıktıda kaçırma sonucunu gözlemler
- Geçerli 0 değerini başarısızlıktan katı karşılaştırmayla ayırır
İçindekiler
Süper Küresel Değişkenler dersinde istek verisi her zaman dizgi olarak geldi ve eksik anahtar uyarı kanalından duyuldu. Bu derste anahtar var, ama içeriği beklenen biçimde değil: sayı beklenen alana 12a gelmiş. PHP bu değerle karşılaşınca bir şey söyler mi, söylerse hangi kanaldan?
Formun HTML yapısını ve alanların nasıl kurulduğunu M14 anlattı; burada yalnız gönderilen verinin sunucu tarafında nasıl süzüldüğü ölçülüyor. Doğrulama işi için PHP’nin filter_var fonksiyonu kullanılır: bir değeri ve bir süzgeç sabitini alır, süzgeç değeri kabul ederse değeri uygun tipte döndürür, kabul etmezse false döndürür. Çıktıda kaçırma (escaping) için htmlspecialchars kullanılır; kaçırmanın neden gerektiği ve ona karşı alınacak önlemlerin sınıflandırması M25’in konusudur.
Geçersiz Değer Dönüşle Duyulur
İlk ölçüm komut satırında yapılır ve süzgeci elle verilen dizgilerle sınar.
<?php // suzgec.php — filter_var'in gecerli ve gecersiz girdideki donusleri function yaz(mixed $deger): string { return match (true) { $deger === null => 'null', is_bool($deger) => $deger ? 'true' : 'false', default => get_debug_type($deger) . ' ' . $deger, }; } $olcumler = [ 'gecerli sayi' => filter_var('12', FILTER_VALIDATE_INT), 'gecersiz form sayisi' => filter_var('12a', FILTER_VALIDATE_INT), 'null_on_failure' => filter_var('12a', FILTER_VALIDATE_INT, FILTER_NULL_ON_FAILURE), ]; foreach ($olcumler as $ad => $sonuc) { printf("%-24s%s\n", $ad, yaz($sonuc)); }
gecerli sayi int 12 gecersiz form sayisi false null_on_failure null
12 için fonksiyon int 12 döndürür: dizgi tam sayıya çevrilmiştir. 12a için false döndürür. Fonksiyon bir uyarı bildirmedi, bir istisna fırlatmadı ve yürütme sürdü; sorun yalnız dönüş değerine bakan kod için duyuluyor. Bu kursun dönüş sınıfıdır: sinyal kendiliğinden gelmez, çağıranın değeri sorgulaması gerekir. IY8. Bu ölçümde fonksiyonların hiçbiri E_WARNING üretmiyor; bu bir ayar değil, filter_var’ın tanımlı davranışıdır, bu yüzden ölçümde bir hata işleyicisi kurulmadı.
Üçüncü satır, FILTER_NULL_ON_FAILURE bayrağının başarısızlığı false yerine null’a çevirdiğini gösterir. Kanal değişmez, hâlâ dönüş değeridir; yalnız değerin kendisi farklıdır. Bayrağın anlamı sonraki bölümde netleşir: false, mantıksal süzgeç için geçerli bir sonuçtur ve bu bayrak onu başarısızlıktan ayırmak için vardır.
Formu Sunucuya Göndermek
Gerçek bir form gönderimini yerleşik sunucuyla ölçeriz. Betik iki alan okur: yas bir tam sayı olmalı, ad kullanıcı metnidir ve çıktıya kaçırılarak yazılır.
<?php // form.php — POST ile gelen yasi dogrular, adi kacirarak yazar $yas = filter_var($_POST['yas'] ?? '', FILTER_VALIDATE_INT); $ad = $_POST['ad'] ?? ''; if ($yas === false) { echo "gecersiz yas\n"; } else { echo 'yas=', $yas, "\n"; } echo 'ad=', htmlspecialchars($ad), "\n";
# sunucu.sh — formu yerlesik sunucuya gonderir php -S 127.0.0.1:8082 -d display_errors=0 >/dev/null 2>&1 & pid=$! for i in $(seq 1 50); do curl -s -o /dev/null http://127.0.0.1:8082/form.php && break; sleep 0.1; done echo '--- gecerli' curl -s -d 'yas=30' --data-urlencode 'ad=Ayse' -w 'durum=%{http_code}\n' http://127.0.0.1:8082/form.php echo '--- gecersiz yas' curl -s -d 'yas=12a' --data-urlencode 'ad=Ayse' -w 'durum=%{http_code}\n' http://127.0.0.1:8082/form.php echo '--- etiketli ad' curl -s -d 'yas=30' --data-urlencode 'ad=<b>Ayse</b>' -w 'durum=%{http_code}\n' http://127.0.0.1:8082/form.php kill $pid
--- gecerli yas=30 ad=Ayse durum=200 --- gecersiz yas gecersiz yas ad=Ayse durum=200 --- etiketli ad yas=30 ad=<b>Ayse</b> durum=200
Geçerli gönderimde yas=30 yazıldı. Geçersiz gönderimde betik gecersiz yas yazdı, ama durum kodu yine 200: sunucu açısından istek başarıyla işlendi, çünkü doğrulama sonucu PHP için bir hata değil, kodun kendi verdiği bir karardır. Doğrulamanın başarısızlığını istemciye bildirmek, kodun bir durum kodu ya da ileti seçmesine bağlıdır; PHP bunu kendiliğinden yapmaz. IY9. Durum kodu false dönüşünün yaşandığını söylemez; 200 görmek doğrulamanın geçtiği anlamına gelmez.
Üçüncü gönderimde ad alanındaki etiket, htmlspecialchars sayesinde <b>Ayse</b> olarak yazıldı. Kaçırma olmasaydı tarayıcı bu metni biçimlendirme olarak yorumlardı. Bu fonksiyon dönüş değeriyle de sessizdir: hiçbir kanal, değerin etiket içerdiğini bildirmez.
Süzgeç Seçenekleri Aralığı Daraltır
Tip kontrolü çoğu zaman yetmez: yaş alanına 150 ya da -5 yazan biri geçerli bir tam sayı göndermiştir ama geçerli bir yaş göndermemiştir. filter_var bunu üçüncü argümandaki options dizisiyle çözer; min_range ve max_range anahtarları kabul edilen aralığı belirler. Ayrıca süzgeç, değerin başındaki ve sonundaki boşlukları kırpar; bu yüzden formdan gelen ' 30 ' gibi bir değer geçerli sayılır.
<?php // aralik.php — tamsayi suzgecinde aralik ve bosluk davranisi $secenekler = ['options' => ['min_range' => 0, 'max_range' => 120]]; $girdiler = ['30', ' 30 ', '150', '-5', '3.0']; foreach ($girdiler as $girdi) { $sonuc = filter_var($girdi, FILTER_VALIDATE_INT, $secenekler); printf("%-8s%s\n", '[' . $girdi . ']', $sonuc === false ? 'false' : 'int ' . $sonuc); }
[30] int 30 [ 30 ] int 30 [150] false [-5] false [3.0] false
Aralığın dışında kalan 150 ve -5 değerleri 12a ile aynı yolu izler: ikisi de false döndürür. Çağıran bakımından üç farklı sorun, yani biçim hatası, üst sınırın aşılması ve alt sınırın aşılması, tek bir değere indirgenir. Hangisinin olduğunu öğrenmek için kodun girdiyi yeniden incelemesi gerekir; dönüş kanalı yalnız başarısızlığın olduğunu söyler, nedenini taşımaz. 3.0 da reddedilir, çünkü süzgeç ondalık gösterimi tam sayı kabul etmez. IY10. Burada gösterilen kırpma ve ondalık davranışı ölçümün çalıştığı PHP 8 ailesine aittir; ders sınır değerlere güvenmez, aralığı her çağrıda kendisi verir.
Mantıksal Süzgeç false’u Başarısızlıktan Ayırır
FILTER_NULL_ON_FAILURE bayrağının asıl işi mantıksal süzgeçte görünür. FILTER_VALIDATE_BOOLEAN için false geçerli bir sonuçtur: "false", "0" ve boş dizgi onun kabul edilen yazılışlarıdır. Bayrak olmadan, hem geçerli false hem tanınmayan bir metin false döndürür ve çağıran ikisini ayıramaz. Bayrakla tanınmayan metin null olur ve ayrım değerin kendisinde kalır.
<?php // mantiksal.php — mantiksal suzgecte gecerli false ile basarisizligin ayrimi function yaz(mixed $deger): string { return $deger === null ? 'null' : ($deger ? 'true' : 'false'); } foreach (['true', 'on', 'false', '0', '', 'abc'] as $girdi) { $bayraksiz = filter_var($girdi, FILTER_VALIDATE_BOOLEAN); $bayrakli = filter_var($girdi, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE); printf("%-8s bayraksiz=%-6s bayrakli=%s\n", '[' . $girdi . ']', yaz($bayraksiz), yaz($bayrakli)); }
[true] bayraksiz=true bayrakli=true [on] bayraksiz=true bayrakli=true [false] bayraksiz=false bayrakli=false [0] bayraksiz=false bayrakli=false [] bayraksiz=false bayrakli=false [abc] bayraksiz=false bayrakli=null
Bayraksız sütunda false, 0, boş dizgi ve abc aynı görünür; yalnız abc gerçekten geçersizdir. Bayrak abc için null döndürür, diğerleri geçerli false kalır. Bu, önceki bölümlerde sözü edilip ölçülmemiş iddiadır: bayrak başarısızlığı yeni bir kanala taşımaz, mevcut dönüş kanalında false ile null arasında bir ayrım açar. IY11. Bu ayrımdan yararlanmak için çağıranın === null sınaması yapması gerekir; değilleme işleci null ile false’u yine aynı sayar.
Eksik Alan Geçersiz Değerle Aynı Görünür
Doğrulamanın bir tuzağı, alanın hiç gönderilmemesidir. Önceki form.php eksik alanı ?? '' ile boş dizgiye çevirir ve süzgeç boş dizgiyi reddeder; sonuç, 12a gönderilmiş gibi false olur. Ayrım için anahtarın varlığı ayrıca sınanır.
<?php // eksik_alan.php — eksik alan ile gecersiz alanin ayni false'a inmesi $yas = filter_var($_POST['yas'] ?? '', FILTER_VALIDATE_INT); $var = array_key_exists('yas', $_POST) ? 'evet' : 'hayir'; echo 'suzgec=', $yas === false ? 'false' : $yas, ' alan_var=', $var, "\n";
# eksik_alan.sh — alanli ve alansiz iki POST gonderir php -S 127.0.0.1:8082 -d display_errors=0 >/dev/null 2>&1 & pid=$! for i in $(seq 1 50); do curl -s -o /dev/null http://127.0.0.1:8082/eksik_alan.php && break; sleep 0.1; done echo '--- yas=12a' curl -s -d 'yas=12a' -w 'durum=%{http_code}\n' http://127.0.0.1:8082/eksik_alan.php echo '--- alan yok' curl -s -d 'ad=Ayse' -w 'durum=%{http_code}\n' http://127.0.0.1:8082/eksik_alan.php kill $pid
--- yas=12a suzgec=false alan_var=evet durum=200 --- alan yok suzgec=false alan_var=hayir durum=200
İki istekte süzgeç sonucu aynıdır: false. Yalnız array_key_exists farkı gösterir. Eksik alan Süper Küresel Değişkenler dersinde uyarı kanalındaydı; ?? '' onu sessiz kanala çekti ve doğrulama sonunda dönüş kanalına indirdi. Üç kanal, tek bir satırda zincirlenmiştir ve sonuç hiçbir noktada hangisinin devrede olduğunu söylemez. IY12. Hangi kanalın seçildiğini bilmeyen kod, “alan yok” ile “alan bozuk” durumlarını aynı hata iletisiyle karşılar.
Diğer Süzgeçler Aynı Dönüş Yolunu Kullanır
Tam sayı ve mantıksal süzgeçler tek örnek değildir. E-posta ve ondalık sayı süzgeçleri de aynı biçimde çalışır: geçerli girdide değeri, geçersiz girdide false döndürür. Ondalık sayıda ayırıcı nokta olarak kabul edilir; virgül kullanan bir kullanıcının girdisi reddedilir.
<?php // digerleri.php — e-posta ve ondalik sayi suzgeclerinin donusleri $olcumler = [ 'eposta gecerli' => filter_var('[email protected]', FILTER_VALIDATE_EMAIL), 'eposta gecersiz' => filter_var('ad@', FILTER_VALIDATE_EMAIL), 'ondalik nokta' => filter_var('1.5', FILTER_VALIDATE_FLOAT), 'ondalik virgul' => filter_var('1,5', FILTER_VALIDATE_FLOAT), ]; foreach ($olcumler as $ad => $sonuc) { printf("%-18s%s\n", $ad, $sonuc === false ? 'false' : get_debug_type($sonuc) . ' ' . $sonuc); }
eposta gecerli string [email protected] eposta gecersiz false ondalik nokta float 1.5 ondalik virgul false
Dört süzgeç de aynı yoldan konuşur: sinyal dönüş değerindedir ve ayrıntı yoktur. 1,5 reddi, süzgecin yerel ayara bakmadığını gösterir; ayırıcıyı değiştirmek çağıranın görevidir. IY13. Bu dersin bütün ölçümleri tek bir sonuca varır: PHP girdinin geçersizliğini istemciye bildirmez, çağırana yalnız bir değer verir ve sonrası kodun kararıdır.
Sınırlayıcı Ölçüm
Dönüş kanalının zayıf noktası, başarısızlığı sınamanın yoludur. Başarısızlığı false’tan ayırmanın en kısa yolu değeri değilleme işleciyle sınamaktır, ama 0 geçerli bir tam sayıdır.
<?php // sifir.php — gecerli 0 ile basarisizligin ayni sinanmasi $olcumler = [ 'sifir' => filter_var('0', FILTER_VALIDATE_INT), 'gecersiz' => filter_var('0a', FILTER_VALIDATE_INT), ]; foreach ($olcumler as $ad => $sonuc) { $kisa = !$sonuc ? 'basarisiz sanildi' : 'gecerli'; $kati = $sonuc === false ? 'basarisiz' : 'gecerli'; printf("%-10s%s: %-18s%s: %s\n", $ad, 'degilleme', $kisa, 'kati', $kati); }
sifir degilleme: basarisiz sanildi kati: gecerli gecersiz degilleme: basarisiz sanildi kati: basarisiz
0 için filter_var geçerli bir int 0 döndürür. Değilleme işleciyle sınanınca bu değer, false ile aynı görünür ve geçerli girdi başarısız sayılır. Katı karşılaştırma (=== false) ikisini ayırır. IY14. Bu bir PHP tuhaflığı değil, dönüş kanalının doğal sınırıdır: kanal tek bir değerin içine hem sonucu hem başarısızlığı sığdırır ve ayrımı çağıran yapar. Bayrak FILTER_NULL_ON_FAILURE ayrımı değerin kendisine taşır, ama o zaman mantıksal süzgeçte geçerli false ile null ayrışır; her durumda sinyali okuyan kodun hangi değerin hangi anlama geldiğini bilmesi gerekir.
Özet
- Form verisi
stringgelir vefilter_varonu süzgeçle sınar: geçerliyse uygun tipte değer, geçersizsefalsedöner. - Bu dersin ölçü sınıfı dönüştür: geçersiz
12aiçin uyarı da istisna da yoktur; sorun yalnız dönüş değerine bakan kod için duyulur. - Doğrulama başarısızlığı durum kodunu değiştirmez: betik kendi kararıyla
gecersiz yasyazsa da yanıt 200 kalır. htmlspecialcharsetiketleri<ve>biçimine çevirir; kaçırmanın sınıflandırması M25’indir.- Geçerli
0, değilleme işlecinde başarısızlıkla aynı görünür; katı karşılaştırma (=== false) ikisini ayırır.
Sonraki Adım
Bu derste istek tek bir değer taşıyordu ve eksik ya da bozuk alan bir kontrolle yakalandı. Dosya yüklemede ise istek, dosyanın kendisi ve ona eşlik eden bir durum kodu taşır. Dosya Yükleme dersi, yüklenmemiş bir dosyanın move_uploaded_file ile taşınmaya çalışılınca ne döndürdüğünü ve sunucu sınırı aşıldığında $_FILES ile $_POST içinde neyin kaldığını ölçüyor.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.