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

Php 有没有办法将一组元素添加到表单中?,php,zend-framework,zend-form,zend-form-element,Php,Zend Framework,Zend Form,Zend Form Element,我想知道是否有一种方法可以将一组元素添加到zend表单中,就像它们是一个元素一样,我想这很像一个子表单,但子表单的功能似乎太多了 这是我的用例。我创建了一个处理多页表单的类。我希望能够编写逻辑,根据我所在表单的页面更改表单底部的按钮。 我最初认为Zend Form DisplayGroup可以解决我的问题,但您必须先将项目添加到表单,然后再将其添加到显示组,并且不能通过带有附加元素的函数传递显示组。我想要一个函数,类似于 public function setSubmitButtonGroup

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

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

我最初认为Zend Form DisplayGroup可以解决我的问题,但您必须先将项目添加到表单,然后再将其添加到显示组,并且不能通过带有附加元素的函数传递显示组。我想要一个函数,类似于

public function setSubmitButtonGroup($submitButtonGroupElements)
{
     /*Code to set button group*/
}
我现在突然想到使用元素数组,而不是其他东西,并添加逻辑,在渲染时将元素数组添加到表单中。。。但是有没有人有过更好的想法或者以前做过


顺便说一句,如果有人想知道。。。我的初始设计大致基于此部分:

您可以创建一个工厂,接收三个参数:表单元素、当前控制器和当前操作。然后在该工厂中,您可以根据控制器/操作组合调用生成器,并传递表单

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

我不确定我是否正确理解您的问题,但这是我如何做一些事情的

在Zend_Form对象中,您可以将元素作为一个组添加到数组中的` addElements($elements)'。对于Submit按钮等,我有一个类,从中获取$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');

因此,我的问题的复杂性在于知道多页表单的哪一页。使用数组和上述加法器()会有所帮助

简单答案

我的问题的答案是一个数组,可以说它可以在表单“构建”之后,但在呈现之前进行操作,这样我就可以使用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 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;
}

哦哦。。。闪亮的我可以看出这是一个挑战性的选择。但这也需要对我的工作方式进行彻底的重新设计,尽管你的想法过于简单、简单、直截了当。谢谢你的“addElements()”函数。我已经完全忘记了。。。是的,我一直在研究一个与你们这里的想法非常相似的想法,除了不太复杂(并不是说这是不必要的复杂)。我只是将
addElements()
基本上重新实现为一个名为
setSubmitButtongGroup(array$elements)
的函数。我现在不能回答我自己的问题,因为我不知道。谢谢你的好主意!
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;
}