Прежде, чем писать HTML код для формы, нам нужно определить, какие данные мы будем получать от пользователей и каким правилам они должны соответствовать. Для фиксации этой информации можно использовать класс модели данных. Модель данных, как говорится в разделе Модель, это центральное место для хранения и проверки данных, вводимых пользователем.
В зависимости от того, каким образом используются данные ввода, мы можем создать два типа модели данных. Если мы получаем данные, обрабатываем их, а затем удаляем, то используем модель формы; если же получаем данные и сохраняем их в базу данных, используем Active Record. Оба типа моделей данных используют один и тот же базовый класс CModel, который определяет общий интерфейс используемый формой.
Примечание: В примерах этого раздела используются модели формы. Тем не менее, всё может быть в равной степени применено и к моделям Active Record.
Ниже мы создадим класс модели LoginForm
, который будет использоваться для
получения данных, вводимых пользователем на странице авторизации. Поскольку
эти данные используются исключительно в целях аутентификации пользователя и
сохранять их не требуется, то создадим модель LoginForm
как модель формы.
class LoginForm extends CFormModel
{
public $username;
public $password;
public $rememberMe=false;
}
Мы объявили в LoginForm
три атрибута: $username
, $password
и $rememberMe
.
Они используются для хранения имени пользователя, пароля, а также значения опции сохранения
имени пользователя. Так как $rememberMe
по умолчанию имеет значение false
, то изначально
в форме авторизации галочка этой опции будет снята.
Информация: Термин "атрибут" используется, чтобы отделить свойства, определяемые этими переменными-членами класса, от прочих свойств. Здесь атрибут - это свойство, которое используется в основном для хранения данных, вводимых пользователем, или данных, получаемых из базы данных.
В момент, когда пользователь отправляет данные формы, а модель их получает,
нам необходимо удостовериться, что эти данные корректны, прежде, чем мы будем их использовать.
Это осуществляется посредством проверки данных в соответствии с набором правил.
Правила проверки задаются в методе rules()
, который возвращает массив сконфигурированных правил.
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()) // аутентификация производится только если нет ошибок ввода
{
$identity=new UserIdentity($this->username,$this->password);
if($identity->authenticate())
{
$duration=$this->rememberMe ? 3600*24*30 : 0; // 30 days
Yii::app()->user->login($identity,$duration);
}
else
$this->addError('password','Incorrect password.');
}
}
}
В коде, представленном выше, username
и password
- обязательные для заполнения поля,
а поле password
должно быть проверено также на соответствие указанному имени пользователя.
Каждое правило, возвращаемое rules()
, должно быть задано в следующем формате:
array('AttributeList', 'Validator', 'on'=>'ScenarioList', ...дополнительные параметры)
где AttributeList
- строка с именами атрибутов, отделенных запятыми, которые должны
быть проверены в соответствии с правилами; Validator
указывает на тип используемой проверки;
параметр on
- необязательный параметр, устанавливающий список сценариев, где должно
использоваться правило; а также прочие параметры - пары имя-значение, которые используются для
инициализации значений свойств соответствующего валидатора.
Есть три способа указать Validator
в правиле проверки. Во-первых, Validator
может быть именем
метода в классе модели данных, аналогично authenticate
в примере выше. Метод проверки
оформляется следующим образом:
/**
* @param string the name of the attribute to be validated
* @param array options specified in the validation rule
*/
public function ValidatorName($attribute,$params) { ... }
Второй способ - указать Validator
в качестве имени класса. В этом случае для проверки данных в момент применения правила создается
экземпляр класса проверки. Дополнительные параметры в правиле используются для
инициализации значений атрибутов экземпляра. Класс проверки должен быть производным классом от CValidator.
Примечание: Задавая правила для модели Active Record, мы можем использовать специальный параметр
on
. Этот параметр может быть типа'insert'
или'update'
, и правило применяется соответственно в случае добавления или обновления записи. Если параметр не задан, то правило применяется в обоих случаях, когда вызываетсяsave()
.
Третий вариант - предопределить псевдоним класса валидатора. В примере выше, имя
required
- это псевдоним класса CRequiredValidator, который проверяет, чтобы
проверяемое значение атрибута не было пустым. Ниже приведен полный список предопределенных псевдонимов валидаторов,
включенных в состав Yii:
boolean
: псевдоним класса CBooleanValidator, который проверяет, чтобы
атрибут имел значение либо CBooleanValidator::trueValue либо CBooleanValidator::falseValue;
captcha
: псевдоним класса CCaptchaValidator, который проверяет, чтобы
значение атрибута было равно коду верификации на капче;
compare
: псевдоним класса CCompareValidator, который проверяет, чтобы
значение атрибута совпадало со значением другого атрибута или константой;
email
: псевдоним класса CEmailValidator, который отвечает за проверку корректности email адреса;
default
: псевдоним класса CDefaultValueValidator, который присваивает значение
по умолчанию выбранным атрибутам;
exist
: псевдоним класса CExistValidator, который проверяет наличие значения атрибута в указанном столбце таблицы;
file
: псевдоним класса CFileValidator, отвечающего за проверку атрибута на
наличие в нем имени загруженного файла;
filter
: псевдоним класса CFilterValidator, преобразовывающего
атрибут с использованием фильтра;
in
: псевдоним класса CRangeValidator, который проверяет, содержатся ли данные в
заданном наборе значений;
length
: псевдоним класса CStringValidator, который проверяет соответствует ли
длина данных заданному интервалу;
match
: псевдоним класса CRegularExpressionValidator, проверяющего данные
на соответствие регулярному выражению;
numerical
: псевдоним класса CNumberValidator, проверяющего, являются ли
данные корректным числовым значением;
required
: псевдоним класса CRequiredValidator, который проверяет, чтобы
значение атрибута не было пустым;
type
: псевдоним класса CTypeValidator, проверяющего соответствие атрибута
заданному типу данных;
unique
: псевдоним класса CUniqueValidator, который проверяет, являются ли
данные уникальными в пределах поля базы данных;
url
: псевдоним класса CUrlValidator, отвечающего за проверку корректности URL.
Ниже представлены несколько примеров использования предопределенных валидаторов:
// имя пользователя - обязательное поле формы
array('username', 'required'),
// длина имени пользователя должна быть от 3 до 12 символов включительно
array('username', 'length', 'min'=>3, 'max'=>12),
// в сценарии регистрации значения полей "password" и "password2" должны быть равны
array('password', 'compare', 'compareAttribute'=>'password2', 'on'=>'register'),
// в сценарии авторизации поле `password` должно быть проверено на соответствие указанному имени пользователя
array('password', 'authenticate', 'on'=>'login'),
Примечание: возможность присвоения значения атрибуту в зависимости от используемого сценария доступна, начиная с версии 1.0.2.
После того, как создан экземпляр модели данных, нам часто требуется заполнить его данными, которые ввел пользователь. Это можно проделать легко и непринужденно, используя массовое присваивание:
$model=new LoginForm;
$model->scenario='login';
if(isset($_POST['LoginForm']))
$model->attributes=$_POST['LoginForm'];
Примечание: свойство scenario стало доступно, начиная с версии 1.0.4. В процессе массового присваивания данное свойство используется для определения атрибутов, значения которых могут быть массово присвоены. В версиях 1.0.2 и 1.0.3 массовое присваивание в конкретном сценарии осуществляется следующим образом:
$model->setAttributes($_POST['LoginForm'], 'login');
Последнее выражение в примере как раз и является массовым присваиванием, где значение каждой переменной в
$_POST['LoginForm']
присваивается соответствующему атрибуту модели в сценарии login
.
Это эквивалентно следующей операции:
foreach($_POST['LoginForm'] as $name=>$value)
{
if($name является безопасным атрибутом)
$model->$name=$value;
}
Безопасность входных данных задается при помощи метода safeAttributes
и
конкретного сценария. По умолчанию метод возвращает как безопасные все публичные переменные-члены
для CFormModel и все поля таблицы, кроме первичного ключа, - для CActiveRecord. Мы можем переопределить
этот метод, чтобы ограничить безопасные атрибуты в соответствии с требованиями сценария. Например, модель, описывающая
пользователя, может содержать множество различных атрибутов, но в сценарии авторизации нам требуются
только атрибуты username
и password
. Обозначить это можно следующим образом:
public function safeAttributes()
{
return array(
parent::safeAttributes(),
'login' => 'username, password',
);
}
Будет аккуратнее, если структуру значения, возвращаемого методом
safeAttributes
оформить так:
array(
// эти атрибуты могут быть *массово присвоены* в любом сценарии,
// кроме специально обозначенных ниже
'attr1, attr2, ...',
*
// эти атрибуты можно *присвоить массово* только в сценарии 'scenario1'
'scenario1' => 'attr2, attr3, ...',
*
// а эти - только в сценарии 'scenario2'
'scenario2' => 'attr1, attr3, ...',
)
Если модель не завязана на сценарии (т.е. используется только в одном сценарии или же все сценарии работают с единым набором безопасных атрибутов), тогда возвращаемое значение можно упростить до одной строки:
'attr1, attr2, ...'
В случае небезопасных входных данных, мы должны присваивать значения соответствующим атрибутам, используя отдельные операции присваивания, как представлено ниже:
$model->permission='admin';
$model->id=1;
Как только модель заполнена пользовательскими данными, вызываем метод CModel::validate(), чтобы запустить процесс проверки. По итогам проверки метод возвращает положительный или отрицательный результат. Для модели CActiveRecord проверку можно выполнять автоматически в момент вызова метода CActiveRecord::save().
При вызове метода CModel::validate() мы можем указать дополнительным параметром сценарий,
и тогда правила проверки будут применяться только при выполнении соответствующего сценария.
Правило применяется к сценарию тогда, когда опция on
правила не установлена или содержит имя этого сценария.
Если же при вызове CModel::validate() сценарий не указывать, то применяться будут только те правила,
опция on
которых не установлена.
Например, в момент регистрации пользователя для осуществления проверки мы выполняем следующее действие:
$model->scenario='register';
$model->validate();
Примечание: свойство scenario стало доступно, начиная с версии 1.0.4. Метод проверки использует данное свойство для определения правил проверки, которые будут применены. В версиях 1.0.2 и 1.0.3 проверка, ассоциированная со сценарием, осуществляется следующим образом:
$model->validate('register');
Можно указать правила проверки в классе модели формы таким образом:
public function rules()
{
return array(
array('username, password', 'required'),
array('password_repeat', 'required', 'on'=>'register'),
array('password', 'compare', 'on'=>'register'),
);
}
В результате, первое правило будет распространяться на любые сценарии, а два последующих будут применяться
только к сценарию register
.
Примечание: возможность применения правил проверки в зависимости от используемого сценария доступна, начиная с версии 1.0.1.
Чтобы узнать, возникли ли во время выполнения проверки какие-либо ошибки, можно воспользоваться методом CModel::hasErrors(). И если ошибки действительно есть, то получить их можно с помощью метода CModel::getErrors(). Оба метода могут быть использованы как для всех, так и для конкретного атрибута.
Часто при работе с формами для каждого поля требуется отображать его метку. Она подсказывает пользователю, какие данные ему требуется ввести в поле. Мы, конечно, можем задать метки полей в представлении, но, если указать их непосредственно в модели данных, мы выиграем в удобстве и гибкости.
По умолчанию CModel в качестве меток возвращает названия атрибутов. Изменить их можно, если
переопределить метод attributeLabels().
Далее мы увидим, что возможность указания меток в модели данных позволяет быстро создавать сложные формы.
Signup or Login in order to comment.