Yiiのフォームデザイナー

こんにちはhabrayuzery!



私が見たほとんどのYiiプロジェクトでは、フォームの操作は最も単純な方法で編成され、フォームのレンダリングはActiveFormウィジェットを介してビューファイルで決定されました。 はい、テンプレートに収めるのが難しい複雑なフォームの場合、これは確かに正当化されます。 しかし、今日はフォームデザイナーについて話し、それをどのように使用するかを示したいと思います。



フォームデザイナーとは何かがよくわからない場合は、まずドキュメントwww.yiiframework.ru/doc/guide/ru/form.builderの関連セクションに精通することをお勧めします。



すべてがシンプルです。 フォームの操作は、「フォームモデルとテーブルモデルを混在させない」という原則に基づいて構築されています。 そして、そのアイデアは、フォームデザイナの機能をフォームモデルに追加することです。



これを行うには、フォームを継承するクラスを作成します。 つまり フォームの構成に基づいて、フォームモデル自体にレンダリングを決定させましょう。



/** * 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()メソッドを再定義しました。属性はフォーム構成のラベルと等しくなりました。



「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」に次を追加します。

  /** * Automatically add a colon in time rendering * @var boolean */ public $autoAddColonForRender = true;
      
      





そして$ _formClassを変更します

  /** * Class name of form * @var string */ protected $_formClass = 'Form';
      
      







新しいクラス「Form」と「CForm」の後継を作成しましょう。その中で、「$ inputElementClass」プロパティをオーバーライドします。

 class Form extends CForm { /** * The name of the class for representing a form input element. * @var string */ public $inputElementClass = 'FormInputElement'; }
      
      







クラス「FormInputElement」(「CFormInputElement」の後継)を作成しましょう。その中で、「renderLabel()」メソッドを再定義します。

 class FormInputElement extends CFormInputElement { /** * @var string the layout used to render label, input, hint and error. They correspond to the placeholders * "{label}", "{input}", "{hint}" and "{error}". */ public $layout = "{label}\n{input}\n{error}\n{hint}"; /** * Automatically add a colon in time rendering * @var boolean */ public $addColon = null; /** * Renders the label for this input. * * @return string */ 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 ), .... ),
      
      







最後まで読んでくれたすべての人に感謝します。 客観的な批判を歓迎します。



All Articles