Form Doğrulama

Gerekli Kontroller

Kontroller, argümanı kullanıcı doldurmazsa görüntülenecek hata mesajının metni olan setRequired() yöntemiyle gerekli olarak işaretlenir. Herhangi bir bağımsız değişken verilmezse, varsayılan hata mesajı kullanılır.

$form->addText('name', 'Name:')
	->setRequired('Please fill your name.');

Kurallar

addRule() metodu ile kontrollere doğrulama kuralları ekleriz. İlk parametre kural, ikincisi hata mesajı, üçüncüsü ise doğrulama kuralı argümanıdır.

$form->addPassword('password', 'Password:')
	->addRule($form::MinLength, 'Password must be at least %d characters', 8);

Doğrulama kuralları yalnızca kullanıcı öğeyi doldurduysa kontrol edilir.

Nette, isimleri Nette\Forms\Form sınıfının sabitleri olan bir dizi önceden tanımlanmış kuralla birlikte gelir. Bu kuralları tüm öğelere uygulayabiliriz:

sabit açıklama argümanlar
Required setRequired() 'un takma adı
Filled setRequired() 'un takma adı
Blank doldurulmamalıdır
Equal değer parametreye eşittir mixed
NotEqual değer parametreye eşit değil mixed
IsIn değer dizideki bazı elemanlara eşittir array
IsNotIn değer dizideki herhangi bir elemana eşit değil array
Valid girdi doğrulamayı geçer ( koşullar için)

Metin girişleri

addText(), addPassword(), addTextArea(), addEmail(), addInteger(), addFloat() öğeleri için aşağıdaki kurallardan bazıları da uygulanabilir:

MinLength minimum dize uzunluğu int
MaxLength maksimum dize uzunluğu int
Length aralıktaki uzunluk veya tam uzunluk çifti [int, int] veya int
Email geçerli e-posta adresi
URL geçerli URL
Pattern düzenli kalıpla eşleşir string
PatternInsensitive Pattern gibi, ancak büyük/küçük harf duyarsız string
Integer tamsayı
Numeric Integer 'un takma adı
Float tamsayı veya kayan noktalı sayı
Min tamsayı değerinin minimum değeri int|float
Max tamsayı değerinin maksimum değeri int|float
Range aralıktaki değer çifti [int|float, int|float]

Integer, Numeric a Float kuralları değeri otomatik olarak tamsayıya (veya sırasıyla float) dönüştürür. Ayrıca, URL kuralı da şeması olmayan bir adresi kabul eder (örneğin nette.org) ve şemayı tamamlar (https://nette.org). Pattern ve PatternInsensitive içindeki ifadeler tüm değer için geçerli olmalıdır, yani ^ and $ karakterlerine sarılmış gibi olmalıdır.

Ürün Sayısı

addMultiUpload(), addCheckboxList(), addMultiSelect() öğeleri için, seçilen öğelerin veya yüklenen dosyaların sayısını sınırlamak üzere aşağıdaki kuralları da kullanabilirsiniz:

MinLength minimum sayı int
MaxLength maksimum sayı int
Length aralıktaki sayı veya tam sayı çiftleri [int, int] veya int

Dosya Yükleme

addUpload(), addMultiUpload() kontrolleri için aşağıdaki kurallar da kullanılabilir:

MaxFileSize bayt cinsinden maksimum dosya boyutu int
MimeType MIME türü, joker karakterleri kabul eder ('video/*') string|string[]
Image yüklenen dosya JPEG, PNG, GIF, WebP
Pattern dosya adı düzenli ifadeyle eşleşiyor string
PatternInsensitive Pattern gibi, ancak büyük/küçük harf duyarsız string

MimeType ve Image PHP uzantısı fileinfo gerektirir. Bir dosya veya resmin gerekli türde olup olmadığı imzasından anlaşılır. Tüm dosyanın bütünlüğü kontrol edilmez. Bir resmin bozuk olup olmadığını örneğin yüklemeye çalışarak öğrenebilirsiniz.

Hata Mesajları

Pattern ve PatternInsensitive dışındaki tüm önceden tanımlanmış kuralların varsayılan bir hata mesajı vardır, bu nedenle bunlar atlanabilir. Bununla birlikte, tüm özelleştirilmiş mesajları ileterek ve formüle ederek, formu daha kullanıcı dostu hale getireceksiniz.

Varsayılan mesajları configuration'da, Nette\Forms\Validator::$messages dizisindeki metinleri değiştirerek veya çevirmen kullanarak değiştirebilirsiniz.

Hata mesajlarının metninde aşağıdaki joker karakterler kullanılabilir:

%d argümanlardan sonraki kuralları kademeli olarak değiştirir
%n$d n'inci kural argümanıyla yer değiştirir
%label alan etiketi ile değiştirir (iki nokta üst üste olmadan)
%name alan adı ile değiştirir (örneğin name)
%value kullanıcı tarafından girilen değerle değiştirir
$form->addText('name', 'Name:')
	->setRequired('Please fill in %label');

$form->addInteger('id', 'ID:')
	->addRule($form::Range, 'at least %d and no more than %d', [5, 10]);

$form->addInteger('id', 'ID:')
	->addRule($form::Range, 'no more than %2$d and at least %1$d', [5, 10]);

Koşullar

Doğrulama kurallarının yanı sıra koşullar da belirlenebilir. Bunlar kurallar gibi ayarlanır, ancak addCondition() yerine addRule() kullanırız ve elbette bir hata mesajı olmadan bırakırız (koşul sadece sorar):

$form->addPassword('password', 'Password:')
	// eğer şifre 8 karakterden uzun değilse ...
	->addCondition($form::MaxLength, 8)
		// ... o zaman bir sayı içermelidir
		->addRule($form::Pattern, 'Must contain number', '.*[0-9].*');

Koşul, addConditionOn() kullanılarak geçerli olandan farklı bir öğeye bağlanabilir. İlk parametre alana bir referanstır. Aşağıdaki durumda, e-posta yalnızca onay kutusu işaretliyse (yani değeri true ise) gerekli olacaktır:

$form->addCheckbox('newsletters', 'send me newsletters');

$form->addEmail('email', 'Email:')
	// onay kutusu işaretliyse ...
	->addConditionOn($form['newsletters'], $form::Equal, true)
		// ... e-posta gerektirir
		->setRequired('E-posta adresinizi doldurun');

Koşullar elseCondition() ve endCondition() yöntemleri ile karmaşık yapılar halinde gruplandırılabilir.

$form->addText(/* ... */)
	->addCondition(/* ... */) // ilk koşul karşılanırsa
		->addConditionOn(/* ... */) // ve ikinci koşulu da başka bir eleman üzerinde
			->addRule(/* ... */) // bu kuralı gerektirir
		->elseCondition() // ikinci koşul karşılanmazsa
			->addRule(/* ... */) // bu kuralları gerektirir
			->addRule(/* ... */)
		->endCondition() // ilk koşula geri dönüyoruz
		->addRule(/* ... */);

Nette, toggle() yöntemini kullanarak JavaScript tarafında bir koşulun yerine getirilip getirilmemesine tepki vermek çok kolaydır, bkz.

Kontroller Arasındaki Referanslar

Kural veya koşul bağımsız değişkeni başka bir öğeye referans olabilir. Örneğin, text adresinin length alanının değeri kadar karaktere sahip olduğunu dinamik olarak doğrulayabilirsiniz:

$form->addInteger('length');
$form->addText('text')
	->addRule($form::Length, null, $form['length']);

Özel Kurallar ve Koşullar

Bazen Nette'deki yerleşik doğrulama kurallarının yeterli olmadığı ve kullanıcıdan gelen verileri kendi yöntemimizle doğrulamamız gereken bir durumla karşılaşırız. Nette'de bu çok kolaydır!

addRule() veya addCondition() yöntemlerine ilk parametre olarak herhangi bir geri çağırma iletebilirsiniz. Geri arama, öğenin kendisini ilk parametre olarak kabul eder ve doğrulamanın başarılı olup olmadığını gösteren bir boolean değeri döndürür. addRule() kullanarak bir kural eklerken, ek argümanlar geçirilebilir ve bunlar daha sonra ikinci parametre olarak geçirilir.

Özel doğrulayıcı kümesi böylece statik yöntemlere sahip bir sınıf olarak oluşturulabilir:

class MyValidators
{
	// değerin argüman tarafından bölünebilir olup olmadığını test eder
	public static function validateDivisibility(BaseControl $input, $arg): bool
	{
		return $input->getValue() % $arg === 0;
	}

	public static function validateEmailDomain(BaseControl $input, $domain)
	{
		// ek doğrulayıcılar
	}
}

Bu durumda kullanım çok basittir:

$form->addInteger('num')
	->addRule(
		[MyValidators::class, 'validateDivisibility'],
		'The value must be a multiple of %d',
		8,
	);

Özel doğrulama kuralları JavaScript'e de eklenebilir. Tek gereklilik, kuralın statik bir yöntem olmasıdır. JavaScript doğrulayıcısı için adı, ters eğik çizgiler olmadan sınıf adı \, the underscore _, ve yöntem adı birleştirilerek oluşturulur. Örneğin, App\MyValidators::validateDivisibility öğesini AppMyValidators_validateDivisibility olarak yazın ve Nette.validators nesnesine ekleyin:

Nette.validators['AppMyValidators_validateDivisibility'] = (elem, args, val) => {
	return val % args === 0;
};

Olay onValidate

Form gönderildikten sonra, addRule() tarafından eklenen kurallar tek tek kontrol edilerek ve ardından onValidateolayı çağrılarak doğrulama gerçekleştirilir. İşleyicisi, tipik olarak birden fazla form öğesindeki değerlerin doğru kombinasyonunu doğrulamak üzere ek doğrulama için kullanılabilir.

Bir hata tespit edilirse, bu hata addError() yöntemi kullanılarak forma iletilir. Bu, belirli bir öğe üzerinde veya doğrudan form üzerinde çağrılabilir.

protected function createComponentSignInForm(): Form
{
	$form = new Form;
	// ...
	$form->onValidate[] = [$this, 'validateSignInForm'];
	return $form;
}

public function validateSignInForm(Form $form, \stdClass $data): void
{
	if ($data->foo > 1 && $data->bar > 5) {
		$form->addError('Bu kombinasyon mümkün değil.');
	}
}

İşleme Hataları

Çoğu durumda, geçerli bir formu işlerken bir hata keşfederiz, örneğin veritabanına yeni bir girdi yazdığımızda ve yinelenen bir anahtarla karşılaştığımızda. Bu durumda, addError() yöntemini kullanarak hatayı forma geri iletiriz. Bu, belirli bir öğe üzerinde ya da doğrudan form üzerinde çağrılabilir:

try {
	$data = $form->getValues();
	$this->user->login($data->username, $data->password);
	$this->redirect('Home:');

} catch (Nette\Security\AuthenticationException $e) {
	if ($e->getCode() === Nette\Security\Authenticator::InvalidCredential) {
		$form->addError('Invalid password.');
	}
}

Mümkünse, hatayı doğrudan form öğesine eklemenizi öneririz, çünkü varsayılan oluşturucu kullanılırken yanında görünecektir.

$form['date']->addError('Sorry, this date is already taken.');

Bir forma veya öğeye birden fazla hata mesajı iletmek için addError() adresini tekrar tekrar çağırabilirsiniz. Bunları getErrors() ile alırsınız.

$form->getErrors() adresinin, yalnızca doğrudan forma değil, doğrudan tek tek öğelere iletilenler de dahil olmak üzere tüm hata mesajlarının bir özetini döndürdüğünü unutmayın. Yalnızca forma iletilen hata mesajları $form->getOwnErrors() aracılığıyla alınır.

Girdi Değerlerini Değiştirme

addFilter() yöntemini kullanarak, kullanıcı tarafından girilen değeri değiştirebiliriz. Bu örnekte, posta kodundaki boşlukları tolere edeceğiz ve kaldıracağız:

$form->addText('zip', 'Posta kodu:')
	->addFilter(function ($value) {
		return str_replace(' ', '', $value); // posta kodundan boşlukları kaldır
	})
	->addRule($form::Pattern, 'The postal code is not five digits', '\d{5}');

Filtre, doğrulama kuralları ve koşulları arasında yer alır ve bu nedenle yöntemlerin sırasına bağlıdır; yani filtre ve kural, addFilter() ve addRule() yöntemlerinin sırası ile aynı sırada çağrılır.

JavaScript Doğrulama

Doğrulama kuralları ve koşullarının dili güçlüdür. Tüm yapılar JavaScript'te hem sunucu tarafında hem de istemci tarafında çalışsa da. Kurallar HTML özelliklerinde data-nette-rules JSON olarak aktarılır. Doğrulamanın kendisi, tüm formun submit olaylarını bağlayan, tüm girdileri yineleyen ve ilgili doğrulamaları çalıştıran başka bir komut dosyası tarafından gerçekleştirilir.

Bu komut dosyası, birkaç olası kaynaktan temin edilebilen netteForms.js adresindedir:

Komut dosyasını CDN'den doğrudan HTML sayfasına gömebilirsiniz:

<script src="https://unpkg.com/nette-forms@3/src/assets/netteForms.js"></script>

Ya da yerel olarak projenin ortak klasörüne kopyalayın (örneğin vendor/nette/forms/src/assets/netteForms.min.js adresinden):

<script src="/path/to/netteForms.min.js"></script>

Veya npm aracılığıyla yükleyin:

npm install nette-forms

Ve sonra yükleyin ve çalıştırın:

import netteForms from 'nette-forms';
netteForms.initOnLoad();

Alternatif olarak, doğrudan vendor klasöründen de yükleyebilirsiniz:

import netteForms from '../path/to/vendor/nette/forms/src/assets/netteForms.js';
netteForms.initOnLoad();

Dinamik JavaScript

Adres alanlarını yalnızca kullanıcı ürünleri postayla göndermeyi seçerse mi göstermek istiyorsunuz? Hiç sorun değil. Anahtar bir çift yöntemdir addCondition() & toggle():

$form->addCheckbox('send_it')
	->addCondition($form::Equal, true)
		->toggle('#address-container');

Bu kod, koşul karşılandığında, yani onay kutusu işaretlendiğinde, #address-container HTML öğesinin görünür olacağını söyler. Ve tam tersi. Böylece, alıcının adresini içeren form öğelerini bu kimliğe sahip bir kapsayıcıya yerleştiririz ve onay kutusu tıklandığında gizlenir veya gösterilir. Bu işlem netteForms.js komut dosyası tarafından gerçekleştirilir.

Herhangi bir seçici toggle() yöntemine argüman olarak aktarılabilir. Tarihsel nedenlerden dolayı, başka hiçbir özel karakter içermeyen alfanümerik bir dize, önünde # character. The second optional parameter allows us to reverse the behavior, i.e. if we used toggle('#address-container', false) olduğu gibi bir öğe kimliği olarak kabul edilir, öğe yalnızca onay kutusu işaretlenmemişse görüntülenir.

Varsayılan JavaScript uygulaması, öğeler için hidden özelliğini değiştirir. Ancak, örneğin bir animasyon ekleyerek davranışı kolayca değiştirebiliriz. JavaScript'teki Nette.toggle yöntemini özel bir çözümle geçersiz kılmanız yeterlidir:

Nette.toggle = (selector, visible, srcElement, event) => {
	document.querySelectorAll(selector).forEach((el) => {
		// hide or show 'el' according to the value of 'visible'
	});
};

Doğrulamayı Devre Dışı Bırakma

Bazı durumlarda doğrulamayı devre dışı bırakmanız gerekir. Bir gönderme düğmesinin gönderme işleminden sonra doğrulama yapmaması gerekiyorsa (örneğin İptal veya Önizleme düğmesi), $submit->setValidationScope([]) adresini çağırarak doğrulamayı devre dışı bırakabilirsiniz. Ayrıca, doğrulanacak öğeleri belirterek formu kısmen doğrulayabilirsiniz.

$form->addText('name')
	->setRequired();

$details = $form->addContainer('details');
$details->addInteger('age')
	->setRequired('age');
$details->addInteger('age2')
	->setRequired('age2');

$form->addSubmit('send1'); // Tüm formu doğrular
$form->addSubmit('send2')
	->setValidationScope([]); // Hiçbir şeyi doğrulamaz
$form->addSubmit('send3')
	->setValidationScope([$form['name']]); // Yalnızca 'name' alanını doğrular
$form->addSubmit('send4')
	->setValidationScope([$form['details']['age']]); // Yalnızca 'age' alanını doğrular
$form->addSubmit('send5')
	->setValidationScope([$form['details']]); // Validates 'details' container

Form üzerindeki onValidate olayı her zaman çağrılır ve setValidationScope adresinden etkilenmez. onValidate kapsayıcı üzerindeki olay yalnızca bu kapsayıcı kısmi doğrulama için belirtildiğinde çağrılır.

versiyon: 4.0