Привет читатели!
В большинстве проектов на Yii которые я видел, работа с формами была организована самым простым способом, где рендеринг формы определялся в файле вида через виджет ActiveForm. Да, это безусловно оправдано для сложных форм, которые сложно уместить в какой либо шаблон. Но сегодня я хочу поговорить о конструкторе форм и показать как это применяем мы.
Все просто. Работа с формами у нас построена по принципу «не смешивать модели формы и модели таблиц». А идея состоит в том, что бы в модель формы добавить функциональность конструктора форм.
Для этого создадим класс от которого будут наследоваться наши формы. Т.е. сделаем так, что бы модель формы сама определяла рендеринг исходя из конфигурации формы.
/**
* FormModel.
*
* @author Andrey Nilov <nilov@glavweb.ru>
* @copyright Copyright (c) 2007-2012 Glavweb.Soft, Russia. (http://glavweb.ru)
*/
class FormModel extends CFormModel
{
/**
* Config of the form
* @var array
*/
protected $_formConfig = array();
/**
* Config of the form by default
* @var array
*/
private $_defaultFormConfig = array(
'method' => 'post'
);
/**
* Class name of form
* @var string
*/
protected $_formClass = 'CForm';
/**
* Object of Form
* @var Form
*/
private $_form = null;
/**
* Constructor
*
* @param string $scenario Name of the scenario that this model is used in
* @return void
*/
public function __construct($scenario = '')
{
parent::__construct($scenario);
$this->_setFormConfig();
}
/**
* Sets config of the form
*
* @return void
*/
private function _setFormConfig()
{
$this->_formConfig = array_replace_recursive(
$this->_defaultFormConfig,
$this->_formConfig()
);
}
/**
* Returns config of the form
*
* @return array
*/
protected function _formConfig()
{
return $this->_formConfig;
}
/**
* Returns the attribute labels
*
* @return array Attribute labels (name=>label)
*/
public function attributeLabels()
{
return $this->getLabels();
}
/**
* Returns the config of the form
*
* @return array
*/
public function getFromConfig()
{
return $this->_formConfig;
}
/**
* Sets the config of the form
*
* @param array $config
* @return void
*/
public function setFromConfig(array $config)
{
$this->_formConfig = $config;
}
/**
* Returns labels
*
* @return array
*/
public function getLabels()
{
$labels = array();
if (!empty($this->_formConfig['elements'])) {
foreach ($this->_formConfig['elements'] as $name => $data) {
if (isset($data['label'])) {
$labels[$name] = $data['label'];
}
}
}
return $labels;
}
/**
* Returns object of Form
*
* @return Form
*/
public function getForm()
{
if ($this->_form === null) {
$this->_form = new $this->_formClass($this->_formConfig, $this);
}
return $this->_form;
}
}
Пройдемся по классу более подробно. Массив "$_formConfig" позволяет задать конфигурацию формы. Например:
/**
* Config of the form
* @var array
*/
protected $_formConfig = array(
'activeForm' => array(
'class' => 'CActiveForm',
'id' => 'registration_form',
'enableClientValidation' => true,
'clientOptions' => array(
'validateOnSubmit' => true
)
),
'elements' => array(
....
'name' => array(
'type' => 'text',
'label' => 'ФИО'
),
'organization' => array(
'type' => 'text',
'label' => 'Организация'
),
....
),
'buttons' => array(
'register' => array(
'type' => 'submit',
'label' => 'Регистрация'
)
)
);
Так же для конфигурации формы можно переопределить метод "_formConfig()". Это удобно когда нужно во время конфигурации реализовать какую-то логику.
Свойство "$_formClass" позволяет изменить класс который используется для отображения формы (CForm или его потомок).
Заметьте, что теперь вам не обязательно указывать атрибуты формы. Для этого мы переопределили метод «attributeLabels()» и теперь атрибуты равны лейблам из конфигурации формы.
Получить объект формы (CForm) можно методом «getForm()».
Использование.
Рендеринг формы:
$formModel = new RegistrationForm();
$form = $formModel->getForm();
echo $form;
Использование совместно с моделью таблицы.
$user = new User();
$user->setAttributes($formModel->getAttributes());
$result = $user->save();
На этом сегодня всё, спасибо всем кто дочитал до конца. Объективная критика приветствуется.
Автор: Nilov_A