Zend_Framework 装饰器将 Label 和 ViewHelper 包装在 div 内
我对 zend 装饰混乱很陌生,但我有两个重要的问题我无法解决。问题一后面是一些示例,
$decorate = array(
array('ViewHelper'),
array('Description'),
array('Errors', array('class'=>'error')),
array('Label', array('tag'=>'div', 'separator'=>' ')),
array('HtmlTag', array('tag' => 'li', 'class'=>'element')),
);
...
$name = new Zend_Form_Element_Text('title');
$name->setLabel('Title')
->setDescription("No --- way");
$name->setDecorator($decorate);
该示例输出
<li class="element">
<label for="title" class="required">Title</label>
<input type="text" name="title" id="title" value="">
<p class="hint">No --- way</p>
<ul class="error">
<li>Value is required and can't be empty</li>
</ul>
</li>
问题#1
如何将 label
和 input
包裹在 div 标签周围?所以输出如下:
<li class="element">
<div>
<label for="title" class="required">Title</label>
<input type="text" name="title" id="title" value="">
</div>
<p class="hint">No --- way</p>
<ul class="error">
<li>Value is required and can't be empty</li>
</ul>
</li>
问题 #2
$decorate
数组中 element
的顺序是怎样的? 他们毫无意义!
I am new to this, zend decoration malarchy, but i have two significant questions that i cant get my head around. Question one is followed by some example
$decorate = array(
array('ViewHelper'),
array('Description'),
array('Errors', array('class'=>'error')),
array('Label', array('tag'=>'div', 'separator'=>' ')),
array('HtmlTag', array('tag' => 'li', 'class'=>'element')),
);
...
$name = new Zend_Form_Element_Text('title');
$name->setLabel('Title')
->setDescription("No --- way");
$name->setDecorator($decorate);
Which outputs
<li class="element">
<label for="title" class="required">Title</label>
<input type="text" name="title" id="title" value="">
<p class="hint">No --- way</p>
<ul class="error">
<li>Value is required and can't be empty</li>
</ul>
</li>
The Question #1
How do i wrap the label
and the input
around a div tag? So the output is as follows:
<li class="element">
<div>
<label for="title" class="required">Title</label>
<input type="text" name="title" id="title" value="">
</div>
<p class="hint">No --- way</p>
<ul class="error">
<li>Value is required and can't be empty</li>
</ul>
</li>
The Question #2
What is up with the order of the elements
in the $decorate
array? They MAKE NO SENSE!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
装饰器模式是一种设计模式,用于向现有类添加功能而不更改现有类。相反,装饰器类将自身包装在另一个类周围,并且通常公开与被装饰类相同的接口。
基本示例:
现在,您可能会想,因为
Zend_Form_Decorator_*
类是装饰器,并且有一个render
方法,所以这自动意味着被装饰类的输出' render 方法将始终由装饰器用附加内容包装。但是,通过检查上面的基本示例,我们可以很容易地看出,当然,情况不一定一定如此,正如这个附加(尽管相当无用)示例所示:事实上,这基本上就是很多 < code>Zend_Form_Decorator_* 装饰器可以工作,如果它们具有这种放置功能是有意义的。
对于有意义的装饰器,您可以使用
setOption( 'placement', 'append' )
来控制放置,例如,或者通过传递选项'placement' =>;例如,'append'
到选项数组。例如,对于
Zend_Form_Decorator_PrepareElements
,此放置选项是无用的,因此会被忽略,因为它准备供ViewScript
装饰器使用的表单元素,使其成为不使用 ViewScript 的装饰器之一。不要触及装饰元素的渲染内容。根据各个装饰器的默认功能,装饰类的内容被包装、附加、前置、丢弃或对装饰类进行完全不同的操作,而不直接向内容添加某些内容,然后将内容传递给下一个装饰器。考虑这个简单的例子:
现在,当您为
Zend_Form_Element_*
元素设置装饰器时,它们将按照添加的顺序被包装并最终执行。因此,按照您的示例:...基本上发生的情况如下(为简洁起见,实际的类名被截断):
因此,在检查示例输出时,我们应该能够提取各个装饰器的默认放置行为:
以及你知道吗;这实际上是所有相应装饰器的默认位置。
但现在最困难的部分来了,我们需要做什么才能得到您想要的结果?为了包装
label
和input
我们不能简单地这样做:...因为这将包装所有前面的内容(
ViewHelper
,Description
、Errors
和Label
)与 div,对吗?甚至不...添加的装饰器将被下一个装饰器替换,因为如果装饰器属于同一类,则装饰器将被后面的装饰器替换。相反,您必须给它一个唯一的键:现在,我们仍然面临
divWrapper
将包装所有前面的内容(ViewHelper
,Description
、错误
和标签
)。所以我们需要在这里发挥创意。有很多方法可以实现我们想要的。我将举一个例子,这可能是最简单的:有关
Zend_Form
装饰器的更多说明,我建议阅读 Zend Framework 的首席开发人员 Matthew Weier O'Phinney 的 有关 Zend Form 装饰器的文章The decorator pattern is a design pattern for adding functionality to existing classes without altering those existing classes. In stead, a decorator class wraps itself around another class, and generally exposes the same interface as the decorated class.
Basic example:
Now, you might be tempted to think that because the
Zend_Form_Decorator_*
classes are decorators, and have arender
method, this automatically means the output of the decorated class'render
method will always be wrapped with additional content by the decorator. But on inspection of our basic example above, we can easily see this doesn't necessarily have to be the case at all of course, as illustrated by this additional (albeit fairly useless) example:This is in fact basically how a lot of
Zend_Form_Decorator_*
decorators work, if it makes sense for them to have this placement functionality.For decorators where it makes sense, you can control the placement with the
setOption( 'placement', 'append' )
for instance, or by passing the option'placement' => 'append'
to the options array, for instance.For
Zend_Form_Decorator_PrepareElements
, for instance, this placement option is useless and therefor ignored, as it prepares form elements to be used by aViewScript
decorator, making it one of the decorators that doesn't touch the rendered content of the decorated element.Depending on the default functionality of the individual decorators, either the content of the decorated class is wrapped, appended, prepended, discarded or something completely different is done to the decorated class, without adding something directly to the content, before passing along the content to the next decorator. Consider this simple example:
Now, when you set the decorators for a
Zend_Form_Element_*
element, they will be wrapped, and consequently executed, in the order in which they are added. So, going by your example:... basically what happens is the following (actual class names truncated for brevity):
So, on examining your example output, we should be able to distill the default placement behaviour of the individual decorators:
And what do you know; this actually is the default placement of all respective decorators.
But now comes the hard part, what do we need to do to get the result you are looking for? In order to wrap the
label
andinput
we can't simply do this:... as this will wrap all preceding content (
ViewHelper
,Description
,Errors
andLabel
) with a div, right? Not even... the added decorator will be replaced by the next one, as decorators are replaced by a following decorator if it is of the same class. In stead you would have to give it a unique key:Now, we're still faced with the problem that
divWrapper
will wrap all preceding content (ViewHelper
,Description
,Errors
andLabel
). So we need to be creative here. There's numerous ways to achieve what we want. I'll give one example, that probably is the easiest:For more explanation about
Zend_Form
decorators I'd recommend reading Zend Framework's lead developer Matthew Weier O'Phinney's article about Zend Form Decorators问题 #1
更改装饰器顺序并以这种方式添加 HtmlTag 帮助器:
问题 #2
装饰器是一条链,每个装饰器的输出都会传递到下一个装饰器的输入一,为了被它“装饰”。
默认情况下,它们附加内容(描述、错误)、前置内容(标签..)和/或包裹一些内容(HtmlTag)。但这些都是默认行为,您可以更改其中的大多数行为:
让我们更仔细地了解链中发生的情况:
ViewHelper
使用声明的默认 viewHelper 呈现您的表单元素在表单元素的类中。Label
将标签添加到先前的输出HtmlTag
包装Description
周围元素描述Errors
附加错误消息(如果有)HtmlTag
将所有这些包装在编辑
我在没有测试任何内容的情况下写了这个答案,因此可能会有一些不准确的地方。亲爱的读者,如果您看到一些,请发表评论,我会更新。
Question #1
Change the decorators order and add an HtmlTag helper this way :
Question #2
Decorators are a chain, the output of each one is passed to the input of the next one, in order to be 'decorated' by it.
By default, they append content (description, errors), prepend content (label..) and or wrap something around (HtmlTag). But these are default behaviors, and you can change it for most of them :
Let's have a more closer look to what happens in your chain :
ViewHelper
renders your form element using it's default viewHelper, declared in the form element's class.Label
prepends the label to the previous outputHtmlTag
wraps a<div>
aroundDescription
appends the elements descriptionErrors
appends error messages, if anyHtmlTag
wraps all this in an<li>
EDIT
I wrote this answer without testing anything, so there might be some little inaccuracies here and there. Dear reader, if you see some just drop a comment and i'll update.