Files
yii/docs/guide/ro/form.model.txt
2009-03-01 01:32:35 +00:00

345 lines
13 KiB
Plaintext

Creare model
============
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](/doc/guide/basics.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](/doc/guide/basics.model); daca
datele de la utilizator sunt colectate si apoi salvate in baza de date,
atunci folosim un [active record](/doc/guide/database.ar). Ambele tipuri de model
sunt derivate din aceeasi clasa [CModel] care defineste interfata necesara unui formular.
> Note|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](/doc/guide/database.ar).
Definirea clasei modelului
--------------------------
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.
~~~
[php]
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.
Declarare reguli de validare
----------------------------
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.
~~~
[php]
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:
~~~
[php]
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:
~~~
[php]
/**
* @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].
> Note|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 precizat `on`, regula va fi aplicata in ambele cazuri atunci cand vom
apela metoda `save()`.
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](http://en.wikipedia.org/wiki/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:
~~~
[php]
// 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'),
~~~
Securizarea asignarilor de atribute
-----------------------------------
> Note|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:
~~~
[php]
$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:
~~~
[php]
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:
~~~
[php]
public function safeAttributes()
{
return array(
parent::safeAttributes(),
'login' => 'username, password',
);
}
~~~
Mai precis, valoarea returnata de metoda `safeAttributes` ar trebui sa fie de forma urmatoare:
~~~
[php]
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:
~~~
[php]
'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:
~~~
[php]
$model->permission='admin';
$model->id=1;
~~~
Declansarea validarii
---------------------
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:
~~~
[php]
$model->validate('register');
~~~
Putem declara regulie de validare in clasa modelului formularului in felul urmator:
~~~
[php]
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`.
> Note|Nota: Validarea in functie de scenariu este disponibila incepand cu versiunea 1.0.1 a Yii.
Obtinerea regulilor de validare
-------------------------------
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.
Label-uri de atribute
---------------------
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()|CModel::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.
<div class="revision">$Id: form.model.txt 598 2009-01-29 20:19:28Z qiang.xue $</div>