Bağımsız Kullanılan Formlar
Nette Forms, web formlarının oluşturulmasını ve işlenmesini önemli ölçüde kolaylaştırır. Bu bölümde göstereceğimiz gibi, bunları uygulamalarınızda çerçevenin geri kalanı olmadan tamamen kendi başlarına kullanabilirsiniz.
Ancak, Nette Application ve presenters kullanıyorsanız, sizin için bir kılavuz var: presenters'daki formlar.
İlk Form
Basit bir kayıt formu yazmaya çalışacağız. Kodu şu şekilde görünecektir (tam kod):
use Nette\Forms\Form;
$form = new Form;
$form->addText('name', 'Name:');
$form->addPassword('password', 'Password:');
$form->addSubmit('send', 'Sign up');
Ve onu işleyelim:
$form->render();
ve sonuç aşağıdaki gibi görünmelidir:
Form, Nette\Forms\Form
sınıfının bir nesnesidir ( Nette\Application\UI\Form
sınıfı sunumlarda
kullanılır). İçine isim, şifre ve gönder butonu kontrollerini ekledik.
Şimdi formu yeniden canlandıracağız. $form->isSuccess()
adresine sorarak formun gönderilip
gönderilmediğini ve geçerli bir şekilde doldurulup doldurulmadığını öğreneceğiz. Eğer öyleyse, verileri dökeceğiz.
Formun tanımından sonra ekleyeceğiz:
if ($form->isSuccess()) {
echo 'Form doğru şekilde dolduruldu ve gönderildi';
$data = $form->getValues();
// $data->name isim içeriyor
// $data->password parola içerir
var_dump($data);
}
getValues()
yöntemi, gönderilen verileri bir ArrayHash nesnesi biçiminde döndürür. Bunu nasıl
değiştireceğimizi daha sonra göstereceğiz. $data
değişkeni, kullanıcı
tarafından girilen verilerle birlikte name
ve password
anahtarlarını içerir.
Genellikle verileri, örneğin veritabanına ekleme gibi daha ileri işlemler için doğrudan göndeririz. Ancak, işleme
sırasında bir hata oluşabilir, örneğin kullanıcı adı zaten alınmıştır. Bu durumda, addError()
adresini
kullanarak hatayı forma geri iletiriz ve bir hata mesajıyla birlikte yeniden çizilmesine izin veririz:
$form->addError('Sorry, username is already in use.');
Formu işledikten sonra bir sonraki sayfaya yönlendireceğiz. Bu, formun yenile, geri düğmesine tıklanarak veya tarayıcı geçmişi taşınarak istenmeden yeniden gönderilmesini önler.
Varsayılan olarak, form POST yöntemi kullanılarak aynı sayfaya gönderilir. Her ikisi de değiştirilebilir:
$form->setAction('/submit.php');
$form->setMethod('GET');
Ve hepsi bu kadar :-) İşlevsel ve mükemmel şekilde güvence altına alınmış bir formumuz var.
Daha fazla form denetimi eklemeyi deneyin.
Kontrollere Erişim
Form ve tek tek kontrolleri bileşen olarak adlandırılır. Bunlar, kökü form olan bir bileşen ağacı oluşturur. Tek tek kontrollere aşağıdaki şekilde erişebilirsiniz:
$input = $form->getComponent('name');
// alternatif sözdizimi: $input = $form['name'];
$button = $form->getComponent('send');
// alternatif sözdizimi: $button = $form['send'];
Kontroller unset kullanılarak kaldırılır:
unset($form['name']);
Doğrulama Kuralları
Burada geçerli kelimesi kullanıldı, ancak formun henüz doğrulama kuralları yok. Hadi düzeltelim.
Ad zorunlu olacaktır, bu nedenle onu, argümanı kullanıcı doldurmazsa görüntülenecek hata mesajının metni olan
setRequired()
yöntemiyle işaretleyeceğiz. Herhangi bir argüman verilmezse, varsayılan hata mesajı
kullanılır.
$form->addText('name', 'Name:')
->setRequired('Please enter a name.');
İsim doldurulmadan formu göndermeye çalıştığınızda bir hata mesajının görüntülendiğini ve siz doldurana kadar tarayıcı veya sunucunun formu reddettiğini göreceksiniz.
Aynı zamanda, örneğin girişe sadece boşluk yazarak sistemi aldatamazsınız. Mümkün değil. Nette sol ve sağ boşlukları otomatik olarak keser. Bunu deneyin. Bu, her tek satırlık girişte her zaman yapmanız gereken bir şeydir, ancak genellikle unutulur. Nette bunu otomatik olarak yapar. (Formları kandırmayı deneyebilir ve isim olarak çok satırlı bir dize gönderebilirsiniz. Burada bile Nette aldanmayacak ve satır sonları boşluk olarak değişecektir).
Form her zaman sunucu tarafında doğrulanır, ancak JavaScript doğrulaması da oluşturulur, bu da hızlıdır ve kullanıcı
formu sunucuya göndermek zorunda kalmadan hatayı hemen öğrenir. Bu işlem netteForms.js
betiği tarafından
gerçekleştirilir. Bunu sayfaya ekleyin:
<script src="https://unpkg.com/nette-forms@3"></script>
Formun bulunduğu sayfanın kaynak koduna bakarsanız, Nette'in gerekli alanları required
CSS sınıfına sahip
öğelere eklediğini fark edebilirsiniz. Aşağıdaki stili şablona eklemeyi deneyin, “Ad” etiketi kırmızı olacaktır.
Kullanıcılar için gerekli alanları zarif bir şekilde işaretliyoruz:
<style>
.required label { color: maroon }
</style>
Ek doğrulama kuralları addRule()
yöntemi ile eklenecektir. İlk parametre kuraldır, ikincisi yine hata
mesajının metnidir ve isteğe bağlı doğrulama kuralı argümanı takip edebilir. Bu ne anlama geliyor?
Form, bir sayı olması (addInteger()
) ve belirli sınırlar içinde olması ($form::Range
)
koşuluyla başka bir isteğe bağlı girdi yaş alacaktır. Ve burada addRule()
'un üçüncü argümanı olan
aralığın kendisini kullanacağız:
$form->addInteger('age', 'Age:')
->addRule($form::Range, 'You must be older 18 years and be under 120.', [18, 120]);
Kullanıcı alanı doldurmazsa, alan isteğe bağlı olduğu için doğrulama kuralları doğrulanmayacaktır.
Açıkçası küçük bir yeniden düzenleme için yer mevcut. Hata mesajında ve üçüncü parametrede, sayılar çift olarak
listelenmiştir ve bu ideal değildir. Çok dilli bir form oluşturuyor olsaydık ve sayıları içeren mesajın
birden fazla dile çevrilmesi gerekseydi, değerleri değiştirmek daha zor olurdu. Bu nedenle, %d
ikame karakterleri
kullanılabilir:
->addRule($form::Range, 'You must be older %d years and be under %d.', [18, 120]);
Parola* alanına geri dönelim, bunu gerekli yapalım ve yine mesajdaki yedek karakterleri kullanarak minimum parola
uzunluğunu ($form::MinLength
) doğrulayalım:
$form->addPassword('password', 'Password:')
->setRequired('Pick a password')
->addRule($form::MinLength, 'Your password has to be at least %d long', 8);
Kontrol için kullanıcının şifreyi tekrar girdiği forma passwordVerify
şeklinde bir alan ekleyeceğiz.
Doğrulama kurallarını kullanarak, her iki şifrenin de aynı olup olmadığını kontrol ediyoruz ($form::Equal
).
Ve bir argüman olarak köşeli parantez kullanarak ilk şifreye bir referans veriyoruz:
$form->addPassword('passwordVerify', 'Password again:')
->setRequired('Fill your password again to check for typo')
->addRule($form::Equal, 'Password mismatch', $form['password'])
->setOmitted();
setOmitted()
adresini kullanarak, değerini gerçekten önemsemediğimiz ve yalnızca doğrulama için var olan
bir öğeyi işaretledik. Değeri $data
adresine aktarılmaz.
PHP ve JavaScript'te doğrulama ile tamamen işlevsel bir formumuz var. Nette'nin doğrulama yetenekleri çok daha geniştir, koşullar oluşturabilir, bunlara göre bir sayfanın bölümlerini görüntüleyebilir ve gizleyebilirsiniz, vb. Her şeyi form doğrul ama bölümünde bulabilirsiniz.
Varsayılan Değerler
Form denetimleri için genellikle varsayılan değerler ayarlarız:
$form->addEmail('email', 'Email')
->setDefaultValue($lastUsedEmail);
Genellikle tüm kontroller için varsayılan değerleri aynı anda ayarlamak yararlıdır. Örneğin, form kayıtları düzenlemek için kullanıldığında. Kaydı veritabanından okuruz ve varsayılan değerler olarak ayarlarız:
//$row = ['name' => 'John', 'age' => '33', /* ... */];
$form->setDefaults($row);
Kontrolleri tanımladıktan sonra setDefaults()
adresini çağırın.
Formun Oluşturulması
Varsayılan olarak, form bir tablo olarak işlenir. Bireysel kontroller temel web erişilebilirlik yönergelerini takip eder.
Tüm etiketler şu şekilde oluşturulur <label>
elemanlarıdır ve girişleriyle ilişkilidir, etikete
tıklamak imleci girişe taşır.
Her öğe için herhangi bir HTML niteliği ayarlayabiliriz. Örneğin, bir yer tutucu ekleyin:
$form->addInteger('age', 'Age:')
->setHtmlAttribute('placeholder', 'Please fill in the age');
Bir formu oluşturmanın gerçekten pek çok yolu vardır, bu yüzden bu bölüm oluşturma konusuna ayrılmıştır.
Sınıflarla Eşleme
Form verilerinin işlenmesine geri dönelim. getValues()
yöntemi gönderilen verileri bir ArrayHash
nesnesi olarak döndürür. Bu stdClass
gibi genel bir sınıf olduğundan, onunla çalışırken editörlerdeki
özellikler için kod tamamlama veya statik kod analizi gibi bazı kolaylıklardan yoksun kalacağız. Bu, her form için,
özellikleri ayrı kontrolleri temsil eden özel bir sınıfa sahip olarak çözülebilir. Örneğin:
class RegistrationFormData
{
public string $name;
public int $age;
public string $password;
}
Alternatif olarak, kurucuyu kullanabilirsiniz:
class RegistrationFormData
{
public function __construct(
public string $name,
public int $age,
public string $password,
) {
}
}
Veri sınıfının özellikleri de enum olabilir ve otomatik olarak eşleştirilirler.
Nette'e verileri bize bu sınıfın nesneleri olarak döndürmesini nasıl söyleyebiliriz? Düşündüğünüzden daha kolay. Tek yapmanız gereken parametre olarak hidrate edilecek sınıf adını veya nesneyi belirtmek:
$data = $form->getValues(RegistrationFormData::class);
$name = $data->name;
Parametre olarak bir 'array'
adresi de belirtilebilir ve ardından veriler bir dizi olarak döndürülür.
Formlar konteynerlerden oluşan çok seviyeli bir yapıdan oluşuyorsa, her biri için ayrı bir sınıf oluşturun:
$form = new Form;
$person = $form->addContainer('person');
$person->addText('firstName');
/* ... */
class PersonFormData
{
public string $firstName;
public string $lastName;
}
class RegistrationFormData
{
public PersonFormData $person;
public int $age;
public string $password;
}
Eşleme daha sonra $person
özellik türünden konteyneri PersonFormData
sınıfına eşlemesi
gerektiğini bilir. Özellik bir kapsayıcı dizisi içerecekse, array
türünü sağlayın ve doğrudan
kapsayıcıyla eşlenecek sınıfı iletin:
$person->setMappedType(PersonFormData::class);
Tarayıcı sayfasına yazdıracak olan Nette\Forms\Blueprint::dataClass($form)
yöntemini
kullanarak bir formun veri sınıfı için bir öneri oluşturabilirsiniz. Daha sonra kodu seçmek ve projenize kopyalamak için
tıklamanız yeterlidir.
Çoklu Gönder Düğmeleri
Formda birden fazla düğme varsa, genellikle hangisine basıldığını ayırt etmemiz gerekir. Düğmenin
isSubmittedBy()
yöntemi bize bu bilgiyi döndürür:
$form->addSubmit('save', 'Kaydet');
$form->addSubmit('delete', 'Sil');
if ($form->isSuccess()) {
if ($form['save']->isSubmittedBy()) {
// ...
}
if ($form['delete']->isSubmittedBy()) {
// ...
}
}
Verilerin geçerliliğini doğrulamak için $form->isSuccess()
adresini atlamayın.
Bir form Enter tuşu ile gönderildiğinde, ilk düğme ile gönderilmiş gibi işlem görür.
Güvenlik Açığı Koruması
Nette Framework güvenli olmak için büyük çaba sarf eder ve formlar en yaygın kullanıcı girdisi olduğundan, Nette formları aşılmaz kadar iyidir.
Formları Siteler Arası Komut Dosyası Yazma (XSS) ve Siteler Arası İstek Sahteciliği (CSRF) gibi iyi bilinen saldırı açıklarına karşı korumanın yanı sıra, artık düşünmek zorunda olmadığınız birçok küçük güvenlik görevini de yerine getirir.
Örneğin, girdilerden tüm kontrol karakterlerini filtreler ve UTF-8 kodlamasının geçerliliğini kontrol eder, böylece formdan gelen veriler her zaman temiz olur. Seçim kutuları ve radyo listeleri için, seçilen öğelerin gerçekten sunulanlardan olduğunu ve herhangi bir sahtecilik olmadığını doğrular. Tek satırlı metin girişi için, bir saldırganın oraya gönderebileceği satır sonu karakterlerini kaldırdığından daha önce bahsetmiştik. Çok satırlı girdiler için satır sonu karakterlerini normalleştirir. Ve böyle devam eder.
Nette, çoğu programcının varlığından bile haberdar olmadığı güvenlik açıklarını sizin için düzeltir.
Bahsedilen CSRF saldırısı, bir saldırganın kurbanı, kurbanın tarayıcısında kurbanın o anda oturum açtığı sunucuya sessizce bir istek yürüten bir sayfayı ziyaret etmesi için kandırması ve sunucunun, isteğin kurban tarafından isteğe bağlı olarak yapıldığına inanmasıdır. Bu nedenle Nette, formun başka bir etki alanından POST yoluyla gönderilmesini engeller. Herhangi bir nedenle korumayı kapatmak ve formun başka bir etki alanından gönderilmesine izin vermek istiyorsanız, şunu kullanın:
$form->allowCrossOrigin(); // DİKKAT! Korumayı kapatır!
Bu koruma _nss
adında bir SameSite çerezi kullanır. Bu nedenle, çerezin gönderilebilmesi için ilk
çıktıyı flushing yapmadan önce bir form oluşturun.
SameSite çerez koruması %100 güvenilir olmayabilir, bu nedenle token korumasını açmak iyi bir fikirdir:
$form->addProtection();
Bu korumayı uygulamanızın hassas verileri değiştiren idari bölümündeki formlara uygulamanız şiddetle tavsiye edilir.
Çerçeve, bir oturumda saklanan kimlik doğrulama belirtecini oluşturarak ve doğrulayarak CSRF saldırısına karşı koruma
sağlar (argüman, belirtecin süresi dolmuşsa gösterilen hata mesajıdır). Bu nedenle formu görüntülemeden önce bir
oturumun başlatılmış olması gerekir. Web sitesinin yönetim bölümünde, kullanıcının oturum açması nedeniyle oturum
genellikle zaten başlatılmıştır. Aksi takdirde, oturumu Nette\Http\Session::start()
yöntemi ile başlatın.
Böylece, Nette'deki formlara hızlı bir giriş yapmış olduk. Daha fazla ilham almak için dağıtımdaki örnekler dizinine bakmayı deneyin.