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.