Form Doğrulama

Zorunlu Elemanlar

Zorunlu elemanları setRequired() metoduyla işaretleriz. Argümanı, kullanıcı elemanı doldurmazsa görüntülenecek hata mesajları metnidir. Argüman belirtmezsek, varsayılan hata mesajı kullanılır.

$form->addText('name', 'İsim:')
	->setRequired('Lütfen bir isim girin');

Kurallar

Doğrulama kurallarını elemanlara addRule() metoduyla ekleriz. İlk parametre kuraldır, ikincisi hata mesajları metnidir ve üçüncüsü doğrulama kuralının argümanıdır.

$form->addPassword('password', 'Şifre:')
	->addRule($form::MinLength, 'Şifre en az %d karakter uzunluğunda olmalıdır', 8);

Doğrulama kuralları yalnızca kullanıcı elemanı doldurduğunda kontrol edilir.

Nette, adları Nette\Forms\Form sınıfının sabitleri olan bir dizi önceden tanımlanmış kuralla birlikte gelir. Tüm elemanlar için şu kuralları kullanabiliriz:

sabit açıklama argüman türü
Required zorunlu eleman, setRequired() için takma ad
Filled zorunlu eleman, setRequired() için takma ad
Blank eleman doldurulmamalıdır
Equal değer parametreye eşittir mixed
NotEqual değer parametreye eşit değildir mixed
IsIn değer dizideki bazı öğelere eşittir array
IsNotIn değer dizideki hiçbir öğeye eşit değildir array
Valid eleman doğru doldurulmuş mu? (koşullar için)

Metin Girişleri

addText(), addPassword(), addTextArea(), addEmail(), addInteger(), addFloat() elemanları için aşağıdaki kurallardan bazıları da kullanılabilir:

MinLength minimum metin uzunluğu int
MaxLength maksimum metin uzunluğu int
Length aralıktaki uzunluk veya tam uzunluk çift [int, int] veya int
Email geçerli e-posta adresi
URL mutlak URL
Pattern düzenli ifadeye uyar string
PatternInsensitive Pattern gibi, ancak büyük/küçük harfe duyarsız string
Integer tamsayı değeri
Numeric Integer için takma ad
Float sayı
Min sayısal elemanın minimum değeri int|float
Max sayısal elemanın maksimum değeri int|float
Range aralıktaki değer çift [int|float, int|float]

Integer, Numeric ve Float doğrulama kuralları değeri doğrudan tamsayıya resp. ondalık sayıya dönüştürür. Ve ayrıca URL kuralı şemasız bir adresi de kabul eder (ör. nette.org) ve şemayı ekler (https://nette.org). Pattern ve PatternIcase içindeki ifade tüm değer için geçerli olmalıdır, yani ^ ve $ karakterleriyle çevrelenmiş gibi.

Öğe Sayısı

addMultiUpload(), addCheckboxList(), addMultiSelect() elemanları için, seçilen öğelerin resp. yüklenen dosyaların sayısını sınırlamak üzere aşağıdaki kurallar da kullanılabilir:

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

Dosya Yüklemeleri

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

MaxFileSize bayt cinsinden maksimum dosya boyutu int
MimeType MIME türü, joker karakterlere izin verilir ('video/*') string|string[]
Image JPEG, PNG, GIF, WebP, AVIF resmi
Pattern dosya adı düzenli ifadeye uyar string
PatternInsensitive Pattern gibi, ancak büyük/küçük harfe duyarsız string

MimeType ve Image, PHP fileinfo uzantısını gerektirir. Bir dosyanın veya resmin istenen türde olup olmadığını imzasına göre algılarlar ve tüm dosyanın bütünlüğünü doğrulamazlar. Bir resmin hasarlı olup olmadığını, örneğin onu yüklemeye çalışarak belirleyebilirsiniz.

Hata Mesajları

Pattern ve PatternInsensitive hariç tüm önceden tanımlanmış kuralların varsayılan bir hata mesajı vardır, bu nedenle atlanabilir. Ancak, tüm mesajları özel olarak belirterek ve formüle ederek formu kullanıcı dostu hale getirebilirsiniz.

Varsayılan mesajları yapılandırmada, Nette\Forms\Validator::$messages dizisindeki metinleri düzenleyerek veya çevirmen kullanarak değiştirebilirsiniz.

Hata mesajlarının metninde şu yer tutucu dizeler kullanılabilir:

%d kural argümanlarıyla sırayla değiştirilir
%n$d n'inci kural argümanıyla değiştirilir
%label eleman etiketiyle değiştirilir (iki nokta üst üste olmadan)
%name eleman adıyla değiştirilir (ör. name)
%value kullanıcı tarafından girilen değerle değiştirilir
$form->addText('name', 'İsim:')
	->setRequired('Lütfen %label girin');

$form->addInteger('id', 'ID:')
	->addRule($form::Range, 'en az %d ve en fazla %d', [5, 10]);

$form->addInteger('id', 'ID:')
	->addRule($form::Range, 'en fazla %2$d ve en az %1$d', [5, 10]);

Koşullar

Kurallara ek olarak koşullar da eklenebilir. Bunlar kurallara benzer şekilde yazılır, ancak addRule() yerine addCondition() metodunu kullanırız ve tabii ki herhangi bir hata mesajı belirtmeyiz (koşul sadece sorar):

$form->addPassword('password', 'Şifre:')
	// şifre 8 karakterden uzun değilse
	->addCondition($form::MaxLength, 8)
		// o zaman bir rakam içermelidir
		->addRule($form::Pattern, 'Bir rakam içermelidir', '.*[0-9].*');

Koşul, addConditionOn() kullanarak geçerli olandan başka bir elemana da bağlanabilir. İlk parametre olarak elemana bir referans belirtiriz. Bu örnekte, e-posta yalnızca onay kutusu işaretlendiğinde (değeri true olacaktır) zorunlu olacaktır:

$form->addCheckbox('newsletters', 'bana bülten gönder');

$form->addEmail('email', 'E-posta:')
	// onay kutusu işaretliyse
	->addConditionOn($form['newsletters'], $form::Equal, true)
		// o zaman e-posta iste
		->setRequired('Bir e-posta adresi girin');

Koşullardan elseCondition() ve endCondition() kullanarak karmaşık yapılar oluşturulabilir:

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

Nette'de, toggle() metodunu kullanarak JavaScript tarafında bir koşulun karşılanmasına veya karşılanmamasına çok kolay bir şekilde yanıt verilebilir, bkz. dinamik-javascript.

Başka Bir Elemana Referans

Kural veya koşul argümanı olarak formun başka bir elemanı da iletilebilir. Kural daha sonra tarayıcıda kullanıcı tarafından daha sonra girilen değeri kullanır. Bu şekilde, örneğin password elemanının password_confirm elemanıyla aynı dizeyi içerip içermediğini dinamik olarak doğrulayabilirsiniz:

$form->addPassword('password', 'Şifre');
$form->addPassword('password_confirm', 'Şifreyi onayla')
    ->addRule($form::Equal, 'Girilen şifreler eşleşmiyor', $form['password']);

Özel Kurallar ve Koşullar

Bazen Nette'deki yerleşik doğrulama kurallarının yeterli olmadığı ve kullanıcı verilerini kendi yöntemimizle doğrulamamız gereken bir duruma geliriz. Nette'de bu çok basittir!

addRule() veya addCondition() metotlarına ilk parametre olarak herhangi bir geri arama iletilebilir. Bu, ilk parametre olarak elemanın kendisini alır ve doğrulamanın düzgün bir şekilde yapılıp yapılmadığını belirten bir boole değeri döndürür. addRule() kullanarak bir kural eklerken, ek argümanlar da belirtilebilir, bunlar daha sonra ikinci parametre olarak iletilir.

Böylece statik metotlara sahip bir sınıf olarak kendi doğrulayıcı setimizi oluşturabiliriz:

class MyValidators
{
	// değerin argümana bölünüp bölünemediğini test eder
	public static function validateDivisibility(BaseControl $input, $arg): bool
	{
		return $input->getValue() % $arg === 0;
	}

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

Kullanım daha sonra çok basittir:

$form->addInteger('num')
	->addRule(
		[MyValidators::class, 'validateDivisibility'],
		'Değer %d sayısının katı olmalıdır',
		8,
	);

Özel doğrulama kuralları JavaScript'e de eklenebilir. Koşul, kuralın statik bir metot olmasıdır. JavaScript doğrulayıcısı için adı, ters eğik çizgiler \ olmadan sınıf adının, alt çizgi _ ve metot adının birleştirilmesiyle oluşturulur. Örneğin, App\MyValidators::validateDivisibility AppMyValidators_validateDivisibility olarak yazılır ve Nette.validators nesnesine eklenir:

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

onValidate Olayı

Form gönderildikten sonra, addRule() kullanılarak eklenen tek tek kuralların kontrol edildiği doğrulama gerçekleştirilir ve ardından olay onValidate tetiklenir. İşleyicisi, ek doğrulama için kullanılabilir, tipik olarak formun birden fazla elemanındaki değerlerin doğru kombinasyonunu doğrulamak için.

Bir hata tespit edilirse, addError() metoduyla forma iletiriz. Bu, belirli bir eleman ü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 Sırasındaki Hatalar

Birçok durumda, hatayı ancak geçerli formu işlerken, örneğin veritabanına yeni bir öğe yazarken ve yinelenen anahtarlarla karşılaştığımızda öğreniriz. Bu durumda, hatayı tekrar addError() metoduyla forma iletiriz. Bu, belirli bir eleman üzerinde veya 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('Geçersiz şifre.');
	}
}

Mümkünse, varsayılan oluşturucuyu kullanırken yanında görüntüleneceği için hatayı doğrudan form elemanına eklemenizi öneririz.

$form['date']->addError('Üzgünüz, ancak bu tarih zaten alınmış.');

Forma veya elemana birden fazla hata mesajı iletmek için addError()'ı tekrar tekrar çağırabilirsiniz. Bunları getErrors() kullanarak alırsınız.

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

Girişi Değiştirme

addFilter() metodunu kullanarak kullanıcı tarafından girilen değeri değiştirebiliriz. Bu örnekte, posta kodlarındaki boşlukları tolere edip kaldıracağız:

$form->addText('zip', 'Posta Kodu:')
	->addFilter(function ($value) {
		return str_replace(' ', '', $value); // posta kodundaki boşlukları kaldıracağız
	})
	->addRule($form::Pattern, 'Posta kodu beş basamaklı biçimde değil', '\d{5}');

Filtre, doğrulama kuralları ve koşulları arasına eklenir ve bu nedenle metotların sırası önemlidir, yani filtre ve kural, addFilter() ve addRule() metotlarının sırasıyla çağrılır.

JavaScript Doğrulaması

Koşulları ve kuralları formüle etme dili çok güçlüdür. Tüm yapılar hem sunucu tarafında hem de JavaScript tarafında çalışır. JSON olarak data-nette-rules HTML niteliklerinde iletilirler. Doğrulamanın kendisi daha sonra formun submit olayını yakalayan, tek tek elemanları gözden geçiren ve ilgili doğrulamayı gerçekleştiren betik tarafından yapılır.

Bu betik netteForms.js'dir ve birden fazla olası kaynaktan edinilebilir:

Betiği doğrudan CDN'den HTML sayfasına ekleyebilirsiniz:

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

Veya yerel olarak projenin genel klasörüne kopyalayın (ör. vendor/nette/forms/src/assets/netteForms.min.js'den):

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

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

npm install nette-forms

Ve ardından yükleyip çalıştırın:

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

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

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

Dinamik JavaScript

Adres girme alanlarını yalnızca kullanıcı malların postayla gönderilmesini seçtiğinde mi görüntülemek istiyorsunuz? Sorun değil. Anahtar, addCondition() & toggle() metot çiftidir:

$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 tersi. Alıcının adresini içeren form elemanlarını bu kimliğe sahip bir konteynere yerleştiririz ve onay kutusuna tıklandığında gizlenir veya gösterilirler. Bu, netteForms.js betiği tarafından sağlanır.

toggle() metodunun argümanı olarak herhangi bir seçici iletilebilir. Tarihsel nedenlerden dolayı, başka özel karakterler içermeyen alfanümerik bir dize, öğenin kimliği olarak anlaşılır, yani önünde # karakteri varmış gibi. İkinci isteğe bağlı parametre, davranışı tersine çevirmeyi sağlar, yani toggle('#address-container', false) kullanırsak, öğe yalnızca onay kutusu işaretli olmadığında görüntülenir.

JavaScript'teki varsayılan uygulama, öğelerin hidden özelliğini değiştirir. Ancak, davranışı kolayca değiştirebiliriz, örneğin bir animasyon ekleyebiliriz. JavaScript'te Nette.toggle metodunu kendi çözümümüzle geçersiz kılmamız yeterlidir:

Nette.toggle = (selector, visible, srcElement, event) => {
	document.querySelectorAll(selector).forEach((el) => {
		// 'el' öğesini 'visible' değerine göre gizleyeceğiz veya göstereceğiz
	});
};

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

Bazen doğrulamayı devre dışı bırakmak gerekebilir. Gönderme düğmesine basmak doğrulamayı gerçekleştirmemesi gerekiyorsa ( İptal veya Önizleme düğmeleri için uygundur), $submit->setValidationScope([]) metoduyla devre dışı bırakırız. Yalnızca kısmi doğrulama yapması gerekiyorsa, hangi alanların veya form konteynerlerinin doğrulanacağını belirleyebiliriz.

$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ç doğrulama yapmaz
$form->addSubmit('send3')
	->setValidationScope([$form['name']]); // Yalnızca name öğesini doğrular
$form->addSubmit('send4')
	->setValidationScope([$form['details']['age']]); // Yalnızca age öğesini doğrular
$form->addSubmit('send5')
	->setValidationScope([$form['details']]); // details konteynerini doğrular

setValidationScope, her zaman çağrılacak olan formdaki #onValidate-olayı etkilemez. Konteynerdeki onValidate olayı yalnızca bu konteyner kısmi doğrulama için işaretlenmişse tetiklenir.

versiyon: 4.0