こんにちはhabrayuzery!
私が見たほとんどのYiiプロジェクトでは、フォームの操作は最も単純な方法で編成され、フォームのレンダリングはActiveFormウィジェットを介してビューファイルで決定されました。 はい、テンプレートに収めるのが難しい複雑なフォームの場合、これは確かに正当化されます。 しかし、今日はフォームデザイナーについて話し、それをどのように使用するかを示したいと思います。
フォームデザイナーとは何かがよくわからない場合は、まずドキュメント
www.yiiframework.ru/doc/guide/ru/form.builderの関連セクションに精通することをお勧めします。
すべてがシンプルです。 フォームの操作は、「フォームモデルとテーブルモデルを混在させない」という原則に基づいて構築されています。 そして、そのアイデアは、フォームデザイナの機能をフォームモデルに追加することです。
これを行うには、フォームを継承するクラスを作成します。 つまり フォームの構成に基づいて、フォームモデル自体にレンダリングを決定させましょう。
class FormModel extends CFormModel { protected $_formConfig = array(); private $_defaultFormConfig = array( 'method' => 'post' ); protected $_formClass = 'CForm'; private $_form = null; public function __construct($scenario = '') { parent::__construct($scenario); $this->_setFormConfig(); } private function _setFormConfig() { $this->_formConfig = array_replace_recursive( $this->_defaultFormConfig, $this->_formConfig() ); } protected function _formConfig() { return $this->_formConfig; } public function attributeLabels() { return $this->getLabels(); } public function getFromConfig() { return $this->_formConfig; } public function setFromConfig(array $config) { $this->_formConfig = $config; } 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; } public function getForm() { if ($this->_form === null) { $this->_form = new $this->_formClass($this->_formConfig, $this); } return $this->_form; } }
クラスをさらに詳しく見ていきましょう。 配列「$ _formConfig」を使用すると、フォームの構成を指定できます。 例:
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()メソッドを再定義しました。属性はフォーム構成のラベルと等しくなりました。
「getForm()」メソッドを使用して、フォームオブジェクト(CForm)を取得できます。
使用します。
フォームのレンダリング:
$formModel = new RegistrationForm(); $form = $formModel->getForm(); echo $form;
テーブルモデルと組み合わせて使用します。
$user = new User(); $user->setAttributes($formModel->getAttributes()); $result = $user->save();
フォームの表示をカスタマイズします。 「$ _formConfig」の各要素に対して、「layout」プロパティをオーバーライドしてテンプレートを指定できます。
protected $_formConfig = array( .... 'elements' => array( .... 'name' => array( 'type' => 'text', 'label' => '', 'layout' => "{input}\n{label}\n{hint}\n{error}" ), .... ),
コロンを自動的に追加します。
フォームデザイナの使用時に発生した問題の1つは、フィールドヘッダーの後にコロンを自動的に追加できないことでした。 ラベル内のフォーム構成にコロンが挿入されている場合、エラーが表示されるとコロンが表示されます。 これを修正するために、クラス「CForm」と「CFormInputElement」を拡張し、「FormModel」をわずかに修正します。
「FormModel」に次を追加します。
public $autoAddColonForRender = true;
そして$ _formClassを変更します
protected $_formClass = 'Form';
新しいクラス「Form」と「CForm」の後継を作成しましょう。その中で、「$ inputElementClass」プロパティをオーバーライドします。
class Form extends CForm { public $inputElementClass = 'FormInputElement'; }
クラス「FormInputElement」(「CFormInputElement」の後継)を作成しましょう。その中で、「renderLabel()」メソッドを再定義します。
class FormInputElement extends CFormInputElement { public $layout = "{label}\n{input}\n{error}\n{hint}"; public $addColon = null; public function renderLabel() { $model = $this->getParent()->getModel(); $addColon = $this->addColon !== null ? $this->addColon : $model instanceof FormModel && $model->autoAddColonForRender; $label = $addColon ? $this->getLabel() . ':' : $this->getLabel(); $options = array( 'label' => $label, 'required' => $this->getRequired() ); if (!empty($this->attributes['id'])) { $options['for'] = $this->attributes['id']; } return CHtml::activeLabel($this->getParent()->getModel(), $this->name, $options); } }
「FormModel」の「$ autoAddColonForRender」プロパティを使用すると、すべてのフォーム要素のラベルの後にコロンを自動的に追加できます。 または、フォームの構成時にフォームの各要素に対して個別に定義し、「addColon」に対応する値を設定します。
protected $_formConfig = array( .... 'elements' => array( .... 'name' => array( 'type' => 'text', 'label' => '', 'addColon' => true ), .... ),
最後まで読んでくれたすべての人に感謝します。 客観的な批判を歓迎します。