Inainte de a scrie cod HTML necesar pt un formular, trebuie sa ne decidem de ce fel de date vom avea nevoie de la utilizatori si ce reguli trebuie sa indeplineasca aceste date. O clasa de model poate fi folosita pentru a inregistra aceste date. Un model, asa cum este definit in sb-sectiunea Model, este locul central pentru pastrarea input-urilor de la utilizatori si pentru validarea lor.
In functie de cum folosim input-urile primite de la utilizator, putem crea doua tipuri de modele. Daca datele de la utilizator sunt colectate, folosite si apoi abandonate, atunci cream un model de formular; daca datele de la utilizator sunt colectate si apoi salvate in baza de date, atunci folosim un active record. Ambele tipuri de model sunt derivate din aceeasi clasa CModel care defineste interfata necesara unui formular.
Nota: In general, folosim modele de formular in exemplele din aceasta sectiune. Dar toate aceste exemple pot fi aplicate si modelelor de tip active record.
Mai jos, cream un model LoginForm
folosit pentru a colecta input-urile de la
utilizator dintr-o pagina de logare. Pentru ca informatiile despre logare sunt
folosite doar pentru a autentifica utilizatorul, nu trebuie sa le salvam in baza de date.
Si deci vom crea LoginForm
ca fiind un model de formular.
class LoginForm extends CFormModel
{
public $username;
public $password;
public $rememberMe=false;
}
Am declarat trei atribute in LoginForm
: $username
, $password
si
$rememberMe
. Sunt folosite pentru a pastra username-ul si parola introduse
de catre utilizator (plus optiunea remember me
). Pentru optiunea $rememberMe
,
valoarea implicita este false
, care inseamna ca optiunea va fi initial afisata
ne-bifata.
Info: In loc sa denumim proprietati aceste trei variabile, folosim termenul de atribute pentru a face diferenta fata de proprietatile normale. Un atribut este o proprietate care este in special folosita pentru a pastra date care au venit de la utilizator sau din baza de date.
O data ce utilizatorul trimite datele din formular si modelul este populat, trebuie
sa ne asiguram ca input-urile sunt valide inainte de a ne folosi de ele.
Facem acest lucru prin executarea validarii fata de un set de reguli.
Specificam regulile de validare in metoda rules()
, care ar trebui sa returneze
un array cu configuratia regulilor.
class LoginForm extends CFormModel
{
public $username;
public $password;
public $rememberMe=false;
public function rules()
{
return array(
array('username, password', 'required'),
array('password', 'authenticate'),
);
}
public function authenticate($attribute,$params)
{
if(!$this->hasErrors()) // vrem sa permitem autentificarea doar cand nu sunt erori
{
$identity=new UserIdentity($this->username,$this->password);
if($identity->authenticate())
{
$duration=$this->rememberMe ? 3600*24*30 : 0; // 30 de zile
Yii::app()->user->login($identity,$duration);
}
else
$this->addError('password','Incorrect password.');
}
}
}
In codul de mai sus, username
si password
sunt obligatorii, iar
password
va fi validata de catre metoda authenticate()
.
Fiecare regula returnata de catre metoda rules()
trebuie sa fie in formatul urmator:
array('AttributeList', 'Validator', 'on'=>'ScenarioList', ...optiuni aditionale)
AttributeList
este un string de nume de atribute separate prin virgula
care trebuie sa fie validate cu regula in cauza; Validator
specifica ce fel de
validare ar trebui executata; parametrul on
este optional si specifica
o lista de scenarii in care regula ar trebui sa fie aplicata; optiunile aditionale
sunt date in perechi de nume-valoare care sunt folosite pentru a initializa valorile
proprietatilor corespunzatoare din clasa validator.
Sunt trei cazuri in care putem specifica Validator
in regula de validare.
In primul caz, Validator
poate fi numele unei metode dintr-o clasa de model,
ca de exemplu metoda authenticate
din exemplul de mai sus. Metoda validator trebuie sa
aiba urmatoarea declaratie:
/**
* @param string numele atributului care trebuie validat
* @param array optiuni specificate in regula de validare
*/
public function ValidatorName($attribute,$params) { ... }
In al doilea caz, Validator
poate fi numele unei clase validator. Cand este aplicata
regula, o instanta a acestei clase validator va fi creata pentru a executa validarea
efectiva. Optiunile aditionale din regula sunt folosite pentru a initializa
valorile atributelor instantei. O clasa validator trebui sa fie derivata din CValidator.
Nota: Cand specificam reguli pentru un model de tip active record, putem folosi o optiune speciala
on
. Optiunea poate fi'insert'
sau'update'
, astfel incat regula va fi aplicata doar la inserarea, sau respectiv actualizarea inregistrarii. Daca nu este precizaton
, regula va fi aplicata in ambele cazuri atunci cand vom apela metodasave()
.
In al treilea caz, Validator
poate fi un alias predefinit catre o clasa validator.
In exemplul de mai sus, numele required
este un alias catre CRequiredValidator,
care asigura ca valoarea atributului va contine ceva. Mai jos avem o lista completa de
alias-uri predefinite de validatori:
captcha
: alias pentru of CCaptchaValidator, asigura ca atributul este acelasi
cu codul de verificare afisat intr-un CAPTCHA.
compare
: alias pentru CCompareValidator, asigura ca atributul este egal cu un
alt atribut sau o constanta.
email
: alias pentru CEmailValidator, asigura ca astributul este o adresa
de email valida.
default
: alias pentru CDefaultValueValidator, defineste o valoare implicita
atributelor specificate.
file
: alias pentru CFileValidator, asigura ca atributul contine un nume
pentru un fisier pentru care se face upload.
filter
: alias pentru CFilterValidator, transforma atributul cu un filtru.
in
: alias pentru CRangeValidator, asigura ca atributul este intr-o lista predefinita de valori.
length
: alias pentru CStringValidator, asigura ca lungimea valorii atributului
este intr-un anumit interval.
match
: alias pentru CRegularExpressionValidator, asigura ca valoarea atributului se potriveste
cu o expresie regulata.
numerical
: alias pentru CNumberValidator, asigura ca valoarea atributului este este un numar valid.
required
: alias pentru CRequiredValidator, asigura ca atributul va contine ceva.
type
: alias pentru CTypeValidator, asigura ca atributul este de un anumit tip de date.
unique
: alias pentru CUniqueValidator, asigura ca valoarea atributului este unica
intr-o coloana a unei tabele din baza de date.
url
: alias pentru CUrlValidator, asigura ca valoarea atributului este un URL valid.
Mai jos, prezentam exemple folosind validatori predefiniti:
// username este obligatoriu
array('username', 'required'),
// username trebuie sa aiba intre 3 si 12 caractere
array('username', 'length', 'min'=>3, 'max'=>12),
// in scenariul de inregistrare utilizator, password trebuie sa fie la fel cu password2
array('password', 'compare', 'compareAttribute'=>'password2', 'on'=>'register'),
// in scenariul de logare, password trebuie sa fie analizat de metoda authenticate()
array('password', 'authenticate', 'on'=>'login'),
Nota: Asignarea de atribute in functie de scenariu este disponibila incepand cu versiunea 1.0.2 a Yii.
Dupa ce o instanta a unui model a fost creata, trebuie sa populam atributele sale cu datele trimise de catre utilizatorul web. Putem face acest lucru mai usor folosind o asignare masiva:
$model=new LoginForm;
if(isset($_POST['LoginForm']))
$model->setAttributes($_POST['LoginForm'], 'login');
Ultima instructiune este o asignare masiva care asigneaza fiecare intrare din
$_POST['LoginForm']
la atributul corespunzator din model in scenariul
login
(specificat in al doilea parametru). Codul de mai sus este echivalent cu codul de mai jos:
foreach($_POST['LoginForm'] as $name=>$value)
{
if($name este atribut sigur)
$model->$name=$value;
}
Task-ul de a decide daca o informatie de intrare este sigura sau nu revine
unei metode safeAttributes()
cu un scenariu specificat. In cazul modelului
CFormModel, implicit, metoda returneaza toate variabilele publice ale modelului,
acest lucru insemnand ca toate aceste variabile sunt sigure.
In cazul modelului CActiveRecord, implicit, metoda returneaza toate coloanele
tabelei cu exceptia cheii primare, acest lucru insemnand ca toate aceste atribute sunt sigure.
In practica, trebuie sa suprascriem de obicei aceasta metoda pentru a enumera
acele atribute care sunt intr-adevar sigure, in functie de scenariu.
De exemplu, un model user poate contine multe atribute, dar in scenariul login
avem nevoie doar de atributele username
si password
.
Putem specifica aceasta limitare in felul urmator:
public function safeAttributes()
{
return array(
parent::safeAttributes(),
'login' => 'username, password',
);
}
Mai precis, valoarea returnata de metoda safeAttributes
ar trebui sa fie de forma urmatoare:
array(
// aceste atribute pot fi asignate masiv in orice scenariu
// care nu este specificat mai jos
'attr1, attr2, ...',
*
// aceste atribute pot fi asignate masiv doar in scenariul 1
'scenario1' => 'attr2, attr3, ...',
*
// aceste atribute pot fi asignate masiv doar in scenariul 2
'scenario2' => 'attr1, attr3, ...',
)
Daca un model nu se potriveste cu vreun scenariu (spre exemplu este folosit doar intr-un scenariu, sau toate scenariile impart acelasi set de atribute sigure) valoarea returnata poate fi simplificata sub forma unui singur string:
'attr1, attr2, ...'
In cazul intrarilor de date care nu sunt sigure, trebuie sa le asignam atributelor corespunzatoare folosind instructiuni de asignare individuale, in felul urmator:
$model->permission='admin';
$model->id=1;
O data ce modelul deste populat cu datele trimise de utilizator, putem apela CModel::validate() pentru a declansa procesul de validare a datelor. Metoda returneaza o valoare care indica daca procesul de validare a avut succes sau nu. In cazul modelului CActiveRecord, validarea poate de asemenea fi declansata atunci cand apelam metoda CActiveRecord::save().
Cand apelam CModel::validate(), putem specifica un parametru de scenariu.
Vor fi executate doar regulile de validare care se aplica scenariului respectiv.
O regula de validare se aplica intr-un scenariu daca optiunea on
a regulii
nu este setata, sau daca contine numele de scenariu specificat. Daca nu specificam
scenariul atunci cand apelam CModel::validate(), vor fi executate doar acele reguli
pentru care optiunea on
nu este setata.
De exemplu, executam urmatoarea instructiune pentru a executa validarea in cazul inregistrarii unui utilizator:
$model->validate('register');
Putem declara regulie de validare in clasa modelului formularului in felul urmator:
public function rules()
{
return array(
array('username, password', 'required'),
array('password_repeat', 'required', 'on'=>'register'),
array('password', 'compare', 'on'=>'register'),
);
}
Prin urmare, prima regula va fi aplicata in toate scenariile, in timp ce urmatoarele
doua reguli vor fi aplicate doar in cazul scenariului register
.
Nota: Validarea in functie de scenariu este disponibila incepand cu versiunea 1.0.1 a Yii.
Putem folosi CModel::hasErrors() pentru a verifica daca au fost erori de validare. Daca au fost erori, putem folosi CModel::getErrors() pentru a obtine mesajele de eroare. Ambele metode pot fi folosite pentru toate atributele sau pentru un singur atribut.
Cand proiectam un formular, de obicei trebuie sa afisam un label label pentru fiecare camp input. Label-ul explica utilizatorului ce fel de informatie trebuie introdusa in campul input. Deci putem adauga manual un label intr-un view, ar fi mult mai flexibil si convenabil sa specificam label-ul in modelul formularului.
Implicit, CModel va returna label-ul unui atribut ca fiind numele respectivului atribut. Acest comportament poate fi modificat prin suprascrierea metodei attributeLabels(). Dupa cum vom vedea in urmatoarele sub-sectiuni, specificand label-uri in model ne permite sa cream un formular mult mai puternic si mult mai rapid.
Found a typo or you think this page needs improvement?
Edit it on github !
Signup or Login in order to comment.