有没有办法将一组元素添加到表单?

时间:2011-07-29 15:48:37

标签: php zend-framework zend-form zend-form-element

我想知道是否有一种方法可以将一组元素添加到zend表单中,就像它们是一个元素一样,我想这很像子表单,但似乎子表单的功能可能太多了......

这是我的用例。我创建了一个处理多页表单的类。我希望能够根据我所在表单的页面编写逻辑来更改表单底部的按钮。 Form Page 1 Form Page 2 Form page 3

我原本以为Zend-Form-DisplayGroup会解决我的问题,但是你必须先将这些项添加到表单然后将它们添加到显示组,并且不能通过带有附加元素的函数传递显示组。我希望有一个类似

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

使用元素数组的想法刚刚打我,而不是其他东西,并添加逻辑将元素数组添加到渲染中的表单...但是有没有人有任何“更好”的想法或做到这一点前?

顺便说一下,如果有人想知道......我基本上将我的初始设计基于此部分:Zend Framework Advance Form Usage.

3 个答案:

答案 0 :(得分:1)

你可以让自己成为一个接收三个参数,你的表单元素,当前控制器和当前动作的工厂。然后在该工厂中,您可以根据控制器/操作组合调用构建器并传递表单。

在构建器中,根据存储在不同组件中的相应控制器/操作要求添加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()中只添加当前接口所需的元素。 (我宁愿在每个构建器中重复代码而不是依赖于这种“魔法”,但这是一种可行的方法)。

答案 1 :(得分: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');

答案 2 :(得分:0)

因此,我的问题的复杂性来自知道多页形式的页面。使用数组和上面提到的addElements()帮助。

简单回答

我的问题的答案是一个数组,可以在表单被“构建”之后进行操作,但是在它被渲染之前,我可以使用addElements()添加到表单。

长答案

为了全面了解,想象一下每次按下下一个或上一个按钮,就会遍历一系列子表单。在这种情况下,需要一个函数来处理按钮渲染。我最终使用了一个案例陈述,虽然它不是世界上最好的实现(在父类Form_MultiPage中不可重用),但它有效:

在我扩展我的mulipage表格课程中

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;
}