Menu

PHP Form İşleme: Gönderme, Doğrulama ve Yeniden Gösterme

Bir PHP formu <form method="post"> ile kendisine gönderilir ve betik, $_SERVER['REQUEST_METHOD'] 'POST' olduğunda alanları $_POST['name'] üzerinden okur. Doğrulamayı, alanların yanında hata mesajlarını, girilen değerleri korumayı, onay kutularını ve seçim listelerini ve çıktıyı kaçışlamayı öğrenin.

Bu sayfada çalıştırılabilir editörler var - düzenle, çalıştır ve sonucu anında gör.

Bir PHP formu onu yazdıran betiğe geri gönderilir: adlandırılmış girdilerle <form method="post"> yazın ve $_SERVER['REQUEST_METHOD'] 'POST' olduğunda her alanı $_POST['name'] olarak okuyun. Geri yazdırdığınız her şeyi htmlspecialchars() ile kaçışlayın.

Bu bloğu çalıştırın, forma bir isim yazın ve Send düğmesine basın: aynı betik bu kez $_POST doldurulmuş olarak yeniden çalışır.

Burada her form işleyicinin ihtiyaç duyduğu üç şey olur:

  • Yöntem kontrolü. İlk ziyarette istek bir GET'tir ve işlenecek hiçbir şey yoktur. ?? 'GET' yalnızca dosya REQUEST_METHOD ayarlanmamış olan komut satırından çalıştığında önemlidir; bir web sunucusunda her zaman ayarlıdır.
  • Her alanda ?? ''. Bir alan eksik olabilir (yeniden adlandırılmış bir girdi, bir betiğin gönderdiği bir istek) ve eksik bir anahtarı okumak bir uyarı yazdırır.
  • Çıktıda kaçışlama. İsim sayfaya iki kez geri gider ve htmlspecialchars() <b>Ada</b> gibi bir değerin işaretlemeye dönüşmek yerine metin olarak gösterilmesini sağlar. Ayrıntılar htmlspecialchars sayfasında.

Bir formu doğrulama ve hataları alanların yanında gösterme

Hataları alan adına göre anahtarlanmış bir dizide toplayın. Dizi boşsa form geçerlidir; değilse formu her mesaj kendi alanının altında ve ziyaretçinin girdisi yerinde olacak şekilde yeniden yazdırın. Onu boş, sonra hatalı bir e-postayla, sonra geçerli değerlerle gönderin.

novalidate tarayıcının kendi kontrollerini kapatır, böylece PHP kontrollerinin çalıştığını izleyebilirsiniz. Gerçek bir formda ikisini de tutun: tarayıcı doğrulaması ziyaretçi için bir kolaylıktır, geçerli olan ise PHP doğrulamasıdır, çünkü herkes formunuz olmadan bir istek gönderebilir. filter_var() e-postayı ve tam sayı aralığını birer çağrıda yapar; diğer filtreleri filter_var sayfası anlatır.

Onay kutuları, radyo düğmeleri ve select

Bir metin alanı boş olsa bile her zaman bir değer gönderir. Diğer kontroller göndermez:

  • İşaretsiz bir onay kutusu hiçbir şey göndermez, bu yüzden anahtarı $_POST içinde yoktur.
  • topics[] adlı onay kutuları bir dizi olarak gelir: $_POST['topics'] ['php', 'sql'] olur.
  • Bir radyo grubu veya bir <select> seçilen seçeneğin value değerini gönderir.

Gönderimden sonra seçimi korumak için eşleşen seçeneğe checked veya selected yazdırın. Birkaç kutuyu işaretleyin, bir seviye seçin ve Save düğmesine basın.

Girdiyi okuduktan sonraki iki kontrol göründüğünden daha önemlidir. array_intersect() listenizde olmayan her konuyu atar ve is_string() ile array_key_exists() kontrolü, biri hiç sunmadığınız bir değer (ya da $levels[$level] ifadesinin hata fırlatmasına yol açacak bir dizi) gönderirse seviyeyi bir varsayılana geri koyar. Bir select bir tarayıcının ne gönderebileceğini sınırlar, bir isteğin ne içerebileceğini değil.

Gizli alanlarla çok adımlı formlar

Gizli bir girdi bir değeri göstermeden bir adımdan diğerine taşır. Burada 1. adım bir isim sorar, 2. adım bir dil sorar ve ismi gizli bir alanda birlikte gönderir, 3. adım ise ikisini de gösterir. Üç adımın hepsinden geçin.

Gizli alanlar sayfa kaynağında görünür ve diğer her alan gibi düzenlenebilir, bu yüzden ziyaretçinin kendi yanıtlarını adımlar arasında taşımak için uygundur, ama asla bir fiyat, bir kullanıcı id'si veya bir rol için değil. Onları sunucuda, bir oturumda tutun; bkz. oturumlar ve çerezler.

Post/Redirect/Get: yenilemede yeniden gönderimi durdurma

Başarılı bir POST sonrasında betik doğrudan bir "teşekkürler" sayfası yazdırırsa, yenilemeye basmak tarayıcıdan POST isteğini yeniden göndermesini ister ve sipariş veya yorum iki kez kaydedilir. Çözüm kaydetmek, yönlendirmek ve sonucu bir GET üzerinde göstermektir:

<?php
session_start();

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $errors = validate($_POST);
    if (!$errors) {
        save_comment($_POST);
        $_SESSION['flash'] = 'Comment posted.';
        header('Location: /comments.php', true, 303);
        exit;
    }
    // On errors, fall through and print the form with the messages.
}

$flash = $_SESSION['flash'] ?? null;
unset($_SESSION['flash']);

303 See Other tarayıcıya yönlendirmeyi bir GET ile izlemesini söyler. header() sonrasındaki exit önemlidir: o olmadan betiğin geri kalanı çalışmaya devam eder. Yönlendirme ayrıca herhangi bir çıktıdan önce olmalıdır, yoksa PHP "headers already sent" ile reddeder.

Gerçek formlar ayrıca bir CSRF belirteci ekler: oturumda ve gizli bir alanda saklanan ve gönderimde hash_equals() ile karşılaştırılan rastgele bir değer; böylece başka bir site giriş yapmış bir ziyaretçi adına formunuza gönderim yapamaz.

Doğrulamayı tarayıcı olmadan test etme

Kuralları bir dizi alan ve hataları döndüren bir fonksiyona koyun. Sayfa onu $_POST ile çağırır, siz de istediğiniz herhangi bir diziyle çağırabilirsiniz; bu da uç durumları denemeyi kolaylaştırır. Listeye kendi durumlarınızı ekleyin.

Dördüncü durum insanların unuttuğu durumdur. Bir istek name[]=x gönderebilir, bu da $_POST['name'] değerini bir dizi yapar ve trim() fonksiyonuna bir dizi vermek bir TypeError fırlatıp betiği durdurur. Önce is_string() kontrol etmek düşmanca girdiyi sıradan bir doğrulama hatasına çevirir. Önceki bloklardaki (string) dönüşümü de TypeError hatasını önler, ama diziyi Array kelimesine çevirir ve bir uyarı yazdırır, bu yüzden is_string() daha temiz kontroldür.

Sık yapılan hata: form gönderilmeden $_POST okumak

En yaygın ilk form betiği alanları dosyanın en üstünde okur:

<?php
$name = $_POST['name'];
echo "Hello, $name";

İlk ziyarette hiçbir şey gönderilmemiştir, bu yüzden PHP şunu yazdırır:

Warning: Undefined array key "name" in /var/www/form.php on line 2

Çözüm ilk bloktaki kalıptır: formu yalnızca istek bir POST olduğunda işleyin ve her alanı bir varsayılanla okuyun, $_POST['name'] ?? ''. Uyarı gönderimden sonra görünüyorsa HTML'deki name özniteliğini PHP'deki anahtarla karşılaştırın: name="Name" ve $_POST['name'] farklı anahtarlardır.

Sıkça Sorulan Sorular

Bir PHP formunu aynı sayfaya nasıl gönderirim?

action olmadan (veya action="" ile) <form method="post"> yazın. Tarayıcı geçerli URL'ye geri gönderir, böylece aynı betik formu hem gösterir hem işler: $_SERVER['REQUEST_METHOD'] === 'POST' kontrol edin ve alanları $_POST üzerinden okuyun.

PHP'de form gönderildikten sonra değerleri nasıl korurum?

Gönderilen değeri kaçışlanmış olarak alana geri yazdırın: <input name="email" value="<?= htmlspecialchars($_POST['email'] ?? '') ?>">. Gönderilen değer eşleştiğinde bir onay kutusu için checked, bir seçim seçeneği için selected yazdırın.

PHP'de birden çok onay kutusunun değerlerini nasıl alırım?

Onay kutularına köşeli parantezle biten aynı adı verin: name="topics[]". PHP o zaman işaretli değerleri bir diziye koyar: $_POST['topics']. İşaretsiz kutular hiçbir şey göndermez, bu yüzden $_POST['topics'] ?? [] kullanın ve her değeri sunduğunuz listeye karşı kontrol edin.

Sayfayı yenilemek PHP formumu neden yeniden gönderiyor?

Son istek bir POST idi, bu yüzden tarayıcı yenilemede onu tekrarlar. Başarılı bir gönderimden sonra header('Location: /thanks.php'); exit; ile yönlendirin (Post/Redirect/Get kalıbı). Yenileme o zaman zararsız bir GET isteğini tekrarlar.

PHP'de $_POST kullanmak güvenli mi?

Hayır, $_POST içindeki her değer ziyaretçiden gelir ve HTML, SQL ya da dizge beklediğiniz yerde bir dizi dahil her şey olabilir. Girişte doğrulayın (filter_var, uzunluk ve izin listesi kontrolleri) ve çıkışta kaçışlayın (HTML için htmlspecialchars, SQL için hazırlanmış ifadeler).

Coddy programlama dilleri çizimi

Coddy ile kodlamayı öğren

BAŞLA