Zend_Form:addElementPrefixPath vs addPrefixPath

时间:2012-01-26 13:05:57

标签: zend-framework zend-form zend-decorators

我目前正在使用Zend_Form构建我自己的Form元素集,并希望我的自定义表单中的所有元素都能够使用我的自定义装饰器

所以我创建了一个这样的自定义表单:

<?php
class Nuke_Form extends Zend_Form
{

    public function __construct($options = null)
    {
        $this->addElementPrefixPath('Nuke_Form_Decorator_TwitterBootstrap', 'Nuke/Form/Decorator/TwitterBootstrap/', 'decorator');

        parent::__construct($options);

    }

}

为了完整起见,这是我的装饰者

<?php
class Nuke_Form_Decorator_TwitterBootstrap_ControlGroup extends Zend_Form_Decorator_Abstract
{

    public function render($content)
    {
        $class = $this->getOption('class') ?: "control-group";

        $element = $this->getElement();
        $errors = $element->getMessages();
        if (!empty($errors)) {
            $class .= " error";
        }

        $output = '<div class="' . $class . '">' . $content . '</div>';

        return $output;
    }

}

以及我在控制器中创建的具体表单实现

class App_Form_Index_Test extends Nuke_Form
{
    public function init()
    {
        parent::init();

        $this->addAttribs(array('class' => 'form-horizontal'));

        $username = new Nuke_Form_Element_Text('username');
        $username->setLabel("Gebruikersnaam")
                 ->setDescription("This is a description")
                 ->setRequired(true)
                 ->addValidator('NotEmpty', true)
                 ->addValidator('int');

        $submit = new Zend_Form_Element_Submit('submit');

        $this->addElements(array($username, $submit));
    }
}

但由于某种原因,Elements无法找到装饰器并输出以下异常:

Message: Plugin by name 'ControlGroup' was not found in the registry; used paths: Zend_Form_Decorator_: Zend/Form/Decorator/

分析异常我看到我的插件路径没有添加,即使我已经在Nuke_Form类中使用addElementPrefixPath()显式添加了它。


奇怪的是,当我将PluginPath单独添加到每个自定义元素时,它可以完美地运行,如下所示。

<?php
class Nuke_Form_Element_Text extends Zend_Form_Element_Text
{
    public function init()
    {
        $this->addPrefixPath('Nuke_Form_Decorator_TwitterBootstrap', 'Nuke/Form/Decorator/TwitterBootstrap/', 'decorator');

        $this->addDecorators(array(
            array('ViewHelper', array(
                'helper' => 'formText'
            )),
            array('Errors'),
            array('Description', array(
                'placement' => Zend_Form_Decorator_Abstract::APPEND,
                'class' => 'help-block'
            )),
            array(array('controls' => 'HtmlTag'), array(
                'tag'   => 'div',
                'class' => 'controls',
            )),
            array('Label', array(
                'class' => 'control-label',
                'requiredSuffix' => ' *',
                'placement' => Zend_Form_Decorator_Abstract::PREPEND
            )),
            array('ControlGroup')
        ));
    }
}

我正在使用最新版本的Zend Framework(v1.11.11)。

经过一些研究后我发现addElementPrefixPath()会在调用时添加所有添加的表单元素的路径,我想这就是为什么在Nuke_Form构造函数中调用它时它不起作用,因为当时没有元素有已被添加。但是我们怎么应该使用这种方法呢?我在网上发现了几个在构造函数中成功调用它的例子。我很困惑或忽略了什么。

2 个答案:

答案 0 :(得分:2)

尝试在构造函数中传递它:
$options = array('elementPrefixPath' => 'Nuke/Form/Decorator/TwitterBootstrap/');

或者可能把它放在init()中:

public function __construct($options = null)
{
    parent::__construct($options);

}
public function init() {
    $this->addElementPrefixPath('Nuke_Form_Decorator_TwitterBootstrap_', 'Nuke/Form/Decorator/TwitterBootstrap/', 'decorator');
}

}

我认为在init()中调用它会效果最好。并且不要在这里打电话给parent::init();,它只是Zend_Form中的一个空函数,没有什么可以覆盖。

这样做

我使用了除自定义元素之外的所有代码,我在inti()中设置了elementPrefixPath,并使用addDecorator()对正常的Zend_Form_Element调用了ControlGroup Decorator,这是输出:

<form enctype="application/x-www-form-urlencoded" class="form-horizontal" method="post" action=""><dl class="zend_form">
<div class="control-group"><dt id="username-label"><label for="username" class="required">Gebruikersnaam</label></dt>
<dd id="username-element">
<input type="text" name="username" id="username" value="" />
<p class="description">This is a description</p></dd></div>
<dt id="submit-label">&#160;</dt><dd id="submit-element">
<input type="submit" name="submit" id="submit" value="submit" /></dd></dl></form>

我做的唯一更改是在前缀中添加一个尾随的 _

<?php
class Application_Form_NukeForm extends Zend_Form
{

    public function __construct($options = null)
    {

        parent::__construct($options);

    }
    public function init(){
        $this->addElementPrefixPath('Jgs_Decorator_', '/Jgs/Decorator/', 'decorator');
    }

}

当然我用自己的路径......

<?php
class Application_Form_Test extends Application_Form_NukeForm
{
    public function init()
    {
        parent::init();

        $this->addAttribs(array('class' => 'form-horizontal'));

        $username = new Zend_Form_Element_Text('username');
        $username->setLabel("Gebruikersnaam")
                 ->setDescription("This is a description")
                 ->setRequired(true)
                 ->addValidator('NotEmpty', true)
                 ->addValidator('int')
                ->addDecorator('ControlGroup');

        $submit = new Zend_Form_Element_Submit('submit');

        $this->addElements(array($username, $submit));
    }
}

我只重命名装饰器以适应我的路径

<?php
class Jgs_Decorator_ControlGroup extends Zend_Form_Decorator_Abstract
{

    public function render($content)
    {
        $class = $this->getOption('class') ?: "control-group";

        $element = $this->getElement();
        $errors = $element->getMessages();
        if (!empty($errors)) {
            $class .= " error";
        }

        $output = '<div class="' . $class . '">' . $content . '</div>';

        return $output;
    }

}

我认为你的问题在其他地方...... 我也让__constructor工作,我不得不调整参数以获得正确的选项:

<?php

class Application_Form_NukeForm extends Zend_Form {

    public function __construct($options = array('elementPrefixPath' => array(
            'prefix' => 'Jgs_',
            'path' => '/Jgs/',
            'type' => 'decorator'
    ))) {

        parent::__construct($options);
    }

我真的希望这会有所帮助:)

答案 1 :(得分:0)

class Nuke_Form_Element_Text中如果你调用setDecorators()而不是addDecorators(),你可能会更好,因为它看起来好像你要替换所有的默认装饰器。
你也可以添加{ {1}}