1

要素のグループを1つの要素であるかのようにzendフォームに追加する方法があったかどうか疑問に思っています。サブフォームによく似ていると思いますが、サブフォームの機能が多すぎるようです...

これが私のユースケースです。複数ページのフォームを処理するクラスを作成しました。現在のフォームのページに基づいて、フォームの下部にあるボタンを変更するロジックを記述できるようにしたいと考えています。 フォームページ 1フォームページ 2フォームページ 3

当初は Zend-Form-DisplayGroup で問題が解決すると思っていましたが、最初にアイテムをフォームに追加してから表示グループに追加する必要があり、要素が添付された関数を介して表示グループを渡すことができません。次のような関数が欲しい

public function setSubmitButtonGroup($submitButtonGroupElements)
{
     /*Code to set button group*/
}

要素の配列を使用するというアイデアは、他の何かとは対照的に、今すぐ私を襲い、その要素の配列をレンダリング時にフォームに追加するロジックを追加します...しかし、誰かが「より良い」アイデアを持っているか、これを以前に行ったことがありますか?

ところで、もし誰かが疑問に思っているなら...私はこのセクションに基づいて初期設計を大まかに行っています: Zend Framework Advance Form Usage.

4

3 に答える 3

1

フォーム要素、現在のコントローラー、現在のアクションの3つのパラメーターを受け取るファクトリを作成できます。次に、そのファクトリで、コントローラーとアクションの組み合わせに基づいてビルダーを呼び出し、フォームを渡します。

ビルダーでは、異なるコンポーネントに保存されている対応するコントローラー/アクション要件に基づいて、1、2、または3つのボタンを追加します。完了したら、フォームを工場に返送し、工場がフォームを返送します。

My_Form // your Zend_Form object

My_Form_Factory // Your new factory (see below)

My_Form_Factory_Builder_Controller_Action  // One of your builder (see below)

My_Form_Factory_Component // Extends the corresponding Zend_Form_Elements

// basic factory that can be called like My_Factory::factory($form, $controller, $action)
class My_Form_Factory {
    static public function factory($form, $controller, $action)
        $builderClass = "My_Form_Factory_Builder_" . $controller . '_' . $action;
        $builder = new $builderClass($form);
        return $builder->buildForm();
}

// Basic builder
class My_Form_Factory_Builder_Controller_Action
{
    protected $_form;
    protected $_previousComponent ;
    protected $_nextComponent ;
    protected $_cancelComponent ;

    public function __construct($form)
    {
        $this->_form = $form;
        $this->_previousComponent = new My_Form_Factory_Component_Previous();
        $this->_nextComponent = new My_Form_Factory_Component_Next();
        $this->_cancelComponent = new My_Form_Factory_Component_Cancel();
    }

    public function buildForm()
    {
        $this->_form->addElement($previousCompnent);
        $this->_form->addElement($nextComponent);
        $this->_form->addElement($cancelComponent);

        return $this->_form;
    }
}

インスタンス化を自動化したい場合は、抽象クラスで必要になる可能性のあるすべての異なるコンポーネントを初期化し、buildForm()メソッドでその現在のインターフェイスに必要な要素のみを追加できます。(この種の「魔法」に頼るよりも、各ビルダーでコードを繰り返したいのですが、それを実行するための実行可能な方法です)。

于 2011-07-29T17:05:43.523 に答える
1

あなたの問題を正しく理解しているかどうかはわかりませんが、これは私がいくつかのことを行う方法です。

Zend_Form オブジェクトでは、配列内の `addElements($elements) を使用して、要素をグループとして追加できます。[送信] ボタンなどについては、$elements 配列を取得するクラスがあり、それをポップするだけです。displayGroup も追加しますが、ボタンの場所を個別に簡単に制御します。フォームはオブジェクトであるため、次のような単純なことを行うことができますが、意図を示すために常に参照を追加します。

更新: ボタン操作をシャッフルしました

function addButtons(&$form,$nextName = null) {
    $buttons = $this->getButtons();  // this will be an array with your buttons
    // make sure you have the element names in your buttons arrays
    if ( is_string($nextName) ) {
        $buttons['nextButton']->setLabel($nextName);
    } elseif ( is_bool($nextName) && false === $nextName ) {
        unset($buttons['nextButton'];
    }
    // repeat for other buttons

    $form->addElements($buttons);
    $elementNames = array_keys($buttons);
    $form->addDisplayGroup($elementNames,'buttonGroup',array('legend'=>'Click some buttons'));

}

$this->addButtons($form,'Finish');
于 2011-07-29T17:53:44.290 に答える
0

したがって、私の問題の複雑さは、マルチページフォームのどのページを知っているかということになります。配列と上記のaddElements()を使用すると役に立ちました。

簡単な答え

私の問題に対する答えは、フォームがいわば「構築」された後、レンダリングされる前に、addElements()を使用してフォームに追加できるように操作できる配列でした。

長い答え

全体像を把握するために、次または前のボタンを押すたびに、サブフォームの配列をトラバースしていると想像してください。この場合、ボタンのレンダリングを処理する関数が必要になります。結局、caseステートメントを使用しましたが、これは世界で最高の実装ではありません(親クラスForm_MultiPageで再利用できません)が、機能しました。

私が持っているマルチページフォームクラスの私の拡張で

public function setSubmitControls()
{
    $previous = new Zend_Form_Element_Submit('previous',array(
        'label'=>'previous',
        'required'=>false,
        'ignore'=>false,
        'order'=>9000
    ));
    $cancel = new Zend_Form_Element_Submit('cancel',array(
        'label'=>'Cancel',
        'required'=>false,
        'ignore'=>false,
        'order'=>9003
    ));
    $next = new Zend_Form_Element_Submit('next',array(
        'label'=>'Next',
        'required'=>false,
        'ignore'=>false,
        'order'=>9002
    ));
    $finished = new Zend_Form_Element_submit('finish',array(
        'label'=>'Finish',
        'required'=>false,
        'ignore'=>false,
        'order'=>9004
    ));
    $submitControls = array();
    echo var_dump($this->getCurrentSubForm()->getName());
    switch($this->getCurrentSubForm()->getName())
    {
        case 'billInfo':
            $submitControls = array(
                $next,
                $cancel
            );
        break;
        case 'payerInfo':
            $submitControls = array(
                $previous,
                $next,
                $cancel
            );
        break;
//So on for other subforms
    }
    $this->setSubmitButtonGroup($submitControls);
}

親クラスのForm_Multipageには、

public function setSubmitButtonGroup(array $elements)
{
    $this->_submitButton = $elements;   
}

public function addSubmitButtonGroupToSubForm(Zend_Form_SubForm $subForm)
{
    $subForm->addElements($this->_submitButton);
    return $subForm;
}

この関数でフォームの「ページ」をレンダリングすると呼び出されます

public function prepareSubForm($spec)
{
    if (is_string($spec)) {
        $subForm = $this->{$spec};
    } elseif ($spec instanceof Zend_Form_SubForm) {
        $subForm = $spec;
    } else {
        throw new Exception('Invalid argument passed to ' .
                            __FUNCTION__ . '()');
    }
    $subform = $this->setSubFormDecorators($subForm);
    $subform = $this->addSubmitButtonGroupToSubForm($subForm);
    $subform = $this->addSubFormActions($subForm);
    $subform->setMethod($this->getMethod());
    return $subForm;
}
于 2011-08-05T20:11:04.220 に答える