2

好的,我是 Zend 框架的新手,如果这有点无知,请原谅。

现在我有一个内置在表格中的表格,表格看起来像

<table>
  <tr>
    <td><label><input>[Text]</td>
  </tr>
  <tr>
    <td><label><input>[Text]</td>
  </tr>
  <tr>
    <td><label><input>[Text]</td>
  </tr>
</table>

最初建造它的人为我正在为之工作的人们留下了一些东西。这些同样的人现在想要基本上有一个看起来像..

<table>
  <tr>
    <td><label><input>[Text]</td>
  </tr>
</table>
<table>
  <tr>
    <td><label><input>[Text]</td>
  </tr>
  <tr>
    <td><label><input>[Text]</td>
  </tr>
  <tr>
    <td><label><input>[Text]</td>
  </tr>
</table>

该表目前通过 foreach 语句推出,因为字段是动态的并且是基于角色的。本质上,代码会吐出一个完整的表单元素数组,然后 foreach 将其构建出来。我对此非常了解。但我的主要问题是,有没有办法打破桌子,可以这么说,然后推出另一个?

总的来说,我想在本质上注入</tr></table><br><table>一些方法,以便我可以拥有 2 个不同的表。

用循环更新 我必须排除一些变量和一些类似的东西,作为正在进行的propietray的一部分,所以我不允许在网络上发布任何代码,所以说这是一个最小版本,剥离了任何可能使很明显

$form = new form_TableForm(self::CHANGEPREFS);
        $form->setAction($this->_helper->url('saveprefs'));
    foreach ($defaults as $name => $value)
            {
               if ($name == 'xxx1' && (!xxx::eval('xxx','view') || $zzz)) continue;
               if ($name == 'xxx2' && !xxx::eval('xxx','view')) continue;
               if ($name == 'xxx3' && !xxx::eval('xxx','alerts')) continue;
               if ($name == 'xxx4' && !xxx::eval('xxx','alerts')) continue;

               $element = new Zend_Form_Element_Checkbox($name);
               $element->setLabel($this->_helper->Literal->xxx($name));
               if ($value) $element->setValue($value);
               $element->setOptions(array(
                   'required' => false,
                   'fullrow' => true
                   ));
               $form->addElement($element);
               //if($name == 'xxx5'){$form .= "</table><table>";}
               //bad attempt at injection above
            }
        $form->addDisplayGroup(array('savebutton'), 'buttonsgroup', array('fullrow' => true));
        return $form;
4

1 回答 1

1

It's been a long time since I've used Zend_Form_Decorators but I think the solution will be with those.

A brief overview of Zend_Form and decorators might help.

Zend_Form is sort of the master container of Zend_Form_Element items. These classes have default "decorators" that, when you print the entire Zend_Form object, the class will loop through all the objects and spit out the HTML formatting that's set in it's class.

You can set the decorator HTML when you create your Zend_Form_Element object. In your foreach loop, you're creating the elements so you can do a conditional to modify the specific element that should close/open a new table. But it can be tricky to get to work right due to how Zend_Form generates it's HTML. I recall needing to create a custom decorator because it just wasn't possible to do something fairly easy with the standard decorators.

In your case above, you can't just append some HTML code to the $form object because the $form object is a complex class.

Anyway, enough talk. Try something like this:

// create the form element
$element = new Zend_Form_Element_Checkbox($name);
... // same code as above

// do something different for 'special' items
if($name == 'xxx5'){

    $element->setDecorators(array(
        array('ViewHelper'),
        // you might need to do this instead of the above
        // array('ViewHelper', array('helper' => 'formCheckbox')),
        array('HtmlTag', array(
            'tag' => 'table', 
            'placement'=>'APPEND', 
            'closeOnly' => true)),
        array(
            'decorator' => array('My_Alias_HtmlTag' => 'HtmlTag'),
            'options' => array(
                'tag' => 'table', 
                'placement'=>'APPEND', 
                'openOnly' => true)
        ),
    ));
}

// now add the element to the form object
$form->addElement($element);

Let me try to break this down for you.

$element->setDecorators( array($d1, $d2, [...]) );

This sets the decorators for this element. Each decorator ($d1, $d2, etc) is built upon from the previous decorator. Think of it as $d1 is going to spit out an HTML string and then $d2 will append/prepend it's HTML string to $d1.

array('ViewHelper'),

This is the default decorator to even get to the element to show. If you don't have this, there will be nothing to show. Each element has a standard decorator. I believe this might include it, but you might need to force the default with:

array('ViewHelper', array('helper' => 'formCheckbox')),

Play around with both. At this point the HTML generated should be:

<input type="checkbox" />

or perhaps it will include table row/cell tags. This part I'm a bit rusty on.

<tr><td><input type="checkbox" /></td></tr>

If it doesn't, we can get them added by defining them. But lets move on...

array('HtmlTag', array(
        'tag' => 'table', 
        'placement'=>'APPEND', 
        'closeOnly' => true)),

"HtmlTag" is a standard decorator that ships with Zend_Framework. It basically allows you to add whatever HTML tag you want. The options I set tell it to use the "table" tag, append it to the previous decorator HTML string, and only use the close tag (</table>).

At this point lets assume we just have the input tag for brevity. We now have:

<input type="checkbox" /></table>

Now we want to also add an opening table decorator:

array(
        'decorator' => array('My_Alias_HtmlTag' => 'HtmlTag'),
        'options' => array(
            'tag' => 'table', 
            'placement'=>'APPEND', 
            'openOnly' => true)
    ),

This part might be slightly confusing. Zend_Form doesn't allow you to use the same decorator more than once on a given element. The reason is how the code generates. Basically the decorator name is used like a namespace. If you add two of the same decorators, the later one overrides the former one.

To get around this, you can give it an alias name, that's what this bit of code is doing:

'decorator' => array('My_Alias_HtmlTag' => 'HtmlTag'),

"My_Alias_HtmlTag" can be anything you want, but following the same rules don't use an Alias name twice. You'll need a new Alias name every time.

The rest of the code should be self evident. I want to append an opening table tag to my current HTML string. The final result should be:

<input type="checkbox" /></table><table>

So, when you print out the $form object, when it hits the "specially decorated" elements, it should produce the HTML code above.

Of course, this will take some playing around with. Like I mentioned, I'm a bit rusty with the whole Zend_Form and it's decorators.

There's also a concern that the custom Zend_Form class might be doing unexpected things that might not make this work right.

But give it a try.

I think this blog post by Matthew Weier O'Phinney helped a lot: http://devzone.zend.com/1240/decorators-with-zend_form/

I hope that helps!

Cheers!

update

I had a typo. " 'tag' => 'true' " should have been " 'tag' => 'table'". I updated my previous code.

于 2012-06-06T23:40:44.623 回答