Zend Framework 2 - 表单元素装饰器

Ron*_*Ron 10 php decorator zend-form zend-form-element zend-framework2

我想强制Zend表单进入Twitter Bootstrap风格.我目前遍历表单字段并将表单信息写入我的bootstrap div结构.

我在Zend Framework 1(!)中看到有一种方法可以在装饰器中执行此操作.但出于某种原因,版本2的文档并没有涵盖这一点......

我想做这样的事情:

protected $_format = '<label for="%s">%s</label>'
             . '<input id="%s" name="%s" type="text" value="%s"/>';

public function render($content)
{
    $element = $this->getElement();
    $name    = htmlentities($element->getFullyQualifiedName());
    $label   = htmlentities($element->getLabel());
    $id      = htmlentities($element->getId());
    $value   = htmlentities($element->getValue());

    $markup  = sprintf($this->_format, $name, $label, $id, $name, $value);
    return $markup;
}
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

Ron*_*Ron 17

我现在正在使用partials.我遍历属性,打造如少数例外CSRF,并Submit...这工作相当顺利:

视图

echo $this->partial('partial/form-partial', array(
'form' => $this->form,
'url' =>  $this->url('whatever', array('action' => 'add')))); ?>
Run Code Online (Sandbox Code Playgroud)

局部

<?php
$form = $this->form;
$form->setAttribute ( 'action', $this->url () );
$form->prepare ();

echo $this->form ()->openTag ( $form );
foreach ( $form as $element ) :
?>
    <div
        class="control-group <?php if($this->formElementErrors($element)) echo "error" ?>">
        <label class="control-label"><?php echo $element->getLabel() ?></label>
        <div class="controls">
                <?php echo $this->formElement ( $element );
                    if ($this->formElementErrors ( $element ))
                ?>
            <span class="help-inline"><?php echo $this->formElementErrors($element) ?></span>
        </div>
    </div>
<?php
endforeach;
echo $this->form ()->closeTag ( $form );
?>
Run Code Online (Sandbox Code Playgroud)

为了清楚起见,省略了例外情况......


Var*_*per 6

我是按照@Rufinus提到的那样做的.请参阅本教程,了解如何在ZF2中创建View Helpers http://blog.evan.pro/creating-a-simple-view-helper-in-zend-framework-2

在我的情况下,我只是想用表单项包装表单元素,所以我扩展了原始的ZF2 View Helpers并让它们进行元素的渲染.我刚刚把它们归还了:

查看助手FormCollection.php

<?php
// ./src/Application/View/Helper/FormCollection.php
namespace Application\View\Helper;

use Zend\Form\ElementInterface;
use Zend\Form\View\Helper\FormCollection as BaseFormCollection;

class FormCollection extends BaseFormCollection {
    public function render(ElementInterface $element) {
        return '<ul>'.parent::render($element).'</ul>';
    }
}
Run Code Online (Sandbox Code Playgroud)

查看Helper FormElement.php

<?php
// ./src/Application/View/Helper/FormElement.php
namespace Application\View\Helper;

use Zend\Form\ElementInterface;
use Zend\Form\View\Helper\FormElement as BaseFormElement;

class FormElement extends BaseFormElement {

    public function render(ElementInterface $element) {
        if ($element->getOption('required')) {
            $req = 'required';
        }
        $type = $element->getAttribute('type');
        $name = $element->getAttribute('name');
        return sprintf('<li class="%s %s %s">%s</li>', $name, $req, $type,  parent::render($element));
    }
}
Run Code Online (Sandbox Code Playgroud)

虽然我的视图看起来像这样,并且不需要修改以使更改生效.

<?php 
$form = $this->form;
$form->prepare();
echo $this->form()->openTag($form);
echo $this->formCollection($form);
echo $this->form()->closeTag($form);
Run Code Online (Sandbox Code Playgroud)

像魅力一样工作.


Joh*_*Yin 5

我尝试了 Ron 的 Partial 方法,结果是这样的,这不是 Bootstrap 3 想要的。

<form id="tea" name="tea" method="POST" action="/tea/add">
    ...
    <div class="form-group">
        <label class="control-label">Brand</label>
        <div class="form-control">
            <input type="text" value="" name="brand">
        </div>
    ...
Run Code Online (Sandbox Code Playgroud)

我们知道,为了使用bootstrap 3预定义的Form样式,我们需要为输入元素form-control定义样式,而不是其包装元素。

我的部分方法如下。

echo $this->form()->openTag($form);
foreach ($form as $element) :?>
    <div class="form-group">
        <?php 
            if ($element->getOption('required')) { $req = 'required'; }
            $type = $element->getAttribute('type');
            $name = $element->getAttribute('name'); 
            $label = $element->getLabel();
        ?>
        <?php if ($name == 'id') { ?>
            <div class="hidden"><?php echo $this->formElement($element); ?></div>
        <?php } else if ($name == 'submit') { ?>
            <input class='btn' name='submit' type='submit' value='Add'>
        <?php } else if ($label != '') { ?>
            <label class="control-label"><?php echo $label ?></label>
            <input class='form-control' name='<?php echo $name ?>' type='<?php echo $type ?>'>
        <?php } ?> 
    </div>
<?php 
endforeach;
echo $this->form()->closeTag();
Run Code Online (Sandbox Code Playgroud)

嗯,我们可以得到结果了。

<form id="tea" name="tea" method="POST" action="/tea/add">
    ...
    <div class="form-group">
        <label class="control-label">Brand</label>
        <input class="form-control" type="text" name="brand">
    </div>
...
Run Code Online (Sandbox Code Playgroud)

如何将自定义样式附加到 zf2 表单中已提到:向 Form 元素添加 class 属性。

class TeaForm extends Form
{
    public function __construct($name = null)
    {
        // we want to ignore the name passed
        parent::__construct('tea');

        $this->add(array(
            'name' => 'id',
            'type' => 'Hidden',
        ));
        $this->add(array(
            'name' => 'brand',
            'type' => 'Text',
            'options' => array(
                'label' => 'Brand',
            ),
            /** **define class attribute** **/
        'attributes' => array(
            'class' => 'form-control',
        ),
        ));
....
Run Code Online (Sandbox Code Playgroud)

它看起来很简单,但是,问题是输入元素将被包装到标签元素中,这仍然不是 Bootstrap 3 的意图。

<form id="tea" role="form" name="tea" method="POST" action="/tea/add">
    <input type="hidden" value="" name="id">
    <label>
        <span>Name</span>
        <input class="form-control" type="text" value="" name="name">
    </label>
...
Run Code Online (Sandbox Code Playgroud)

在我看来,Partial 方法仍然是一种灵活且轻便的选择。Tea Box是ZF2的一种实践,上面提到的所有代码和说明都可以在Gibhub上找到