亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費(fèi)注冊(cè) 查看新帖 |

Chinaunix

  平臺(tái) 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 3652 | 回復(fù): 0
打印 上一主題 下一主題

The simplest Zend_Form decorator [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報(bào)告]
發(fā)表于 2010-02-24 08:27 |只看該作者 |倒序?yàn)g覽

I've been seeing ranting and general confusion about
Zend_Form
decorators (as well as the occasional praises), and thought I'd do a mini-series of blog posts showing how they work.
First, some background on the
Decorator design pattern
. One common technique is to define a common interface that both your originating object and decorator will implement; your decorator than accepts the originating object as a dependency, and will either proxy to it or override its methods. Let's put that into code to make it more easily understood:
interface Window
{
    public function isOpen();
    public function open();
    public function close();
}
class StandardWindow implements Window
{
    protected $_open = false;
    public function isOpen()
    {
        return $this->_open;
    }
    public function open()
    {
        if (!$this->_open) {
            $this->_open = true;
        }
    }
    public function close()
    {
        if ($this->_open) {
            $this->_open = false;
        }
    }
}
class LockedWindow implements Window
{
    protected $_window;
    public function __construct(Window $window)
    {
        $this->_window = $window;
        $this->_window->close();
    }
    public function isOpen()
    {
        return false;
    }
    public function open()
    {
        throw new Exception('Cannot open locked windows');
    }
    public function close()
    {
        $this->_window->close();
    }
}

You then create an object of type StandardWindow, pass it to the constructor of LockedWindow, and your window instance now has different behavior. The beauty is that you don't have to implement any sort of "locking" functionality on your standard window class -- the decorator takes care of that for you. In the meantime, you can pass your locked window around as if it were just another window.
One particular place where the decorator pattern is useful is for creating textual representations of objects. As an example, you might have a "Person" object that, by itself, has no textual representation. By using the Decorator pattern, you can create an object that will act as if it were a Person, but also provide the ability to render that Person textually.
In this particular example, we're going to use
duck typing
instead of an explicit interface. This allows our implementation to be a bit more flexible, while still allowing the decorator object to act exactly as if it were a Person object.
class Person
{
    public function setFirstName($name) {}
    public function getFirstName() {}
    public function setLastName($name) {}
    public function getLastName() {}
    public function setTitle($title) {}
    public function getTitle() {}
}
class TextPerson
{
    protected $_person;
    public function __construct(Person $person)
    {
        $this->_person = $person;
    }
    public function __call($method, $args)
    {
        if (!
method_exists
($this->_person, $method)) {
            throw new Exception('Invalid method called on TextPerson: ' .  $method);
        }
        return
call_user_func_array
(
array
($this->_person, $method), $args);
    }
    public function __toString()
    {
        return $this->_person->getTitle() . ' '
               . $this->_person->getFirstName() . ' '
               . $this->_person->getLastName();
    }
}

In this example, you pass your Person instance to the TextPerson constructor. By using method overloading, you are able to continue to call all the methods of Person -- to set the first name, last name, or title -- but you also now gain a string representation via the __toString() method.
This latter example is getting close to how Zend_Form decorators work. The key difference is that instead of a decorator wrapping the element, the element has one or more decorators attached to it that it then injects itself into in order to render. The decorator then can access the element's methods and properties in order to create a representation of the element -- or a subset of it.
Zend_Form decorators all implement a common interface, Zend_Form_Decorator_Interface. That interface provides the ability to set decorator-specific options, register and retrieve the element, and render. A base decorator, Zend_Form_Decorator_Abstract, provides most of the functionality you will ever need, with the exception of the rendering logic.
Let's consider a situation where we simply want to render an element as a standard form text input with a label. We won't worry about error handling or whether or not the element should be wrapped within other tags for now -- just the basics. Such a decorator might look like this:
class My_Decorator_SimpleInput extends Zend_Form_Decorator_Abstract
{
    protected $_format = '%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, $id, $label, $id, $name, $value);
        return $markup;
    }
}

Let's create an element that uses this decorator:
$decorator = new My_Decorator_SimpleInput();
$element   = new Zend_Form_Element('foo',
array
(
    'label'      => 'Foo',
    'belongsTo'  => 'bar',
    'value'      => 'test',
    'decorators' =>
array
($decorator),
));

Rendering this element results in the following markup:
Foo
You could also put this class in your library somewhere, inform your element of that path, and refer to the decorator as simply "SimpleInput" as well:
$element = new Zend_Form_Element('foo',
array
(
    'label'      => 'Foo',
    'belongsTo'  => 'bar',
    'value'      => 'test',
    'prefixPath' =>
array
('decorator' =>
array
(
        'My_Decorator' => 'path/to/decorators/',
    )),
    'decorators' =>
array
('SimpleInput'),
));

This gives you the benefit of re-use in other projects, and also opens the door for providing alternate implementations of that decorator later (a topic for another post).
Hopefully, the above overview of the decorator pattern and this simple example will shed some light on how you can begin writing decorators. I'll be writing additional posts in the coming weeks showing how to leverage decorators to build more complex markup, and will update this post to link to them as they are written.
Update: Fixed text in thrown exception to reflect actual class name; updated label generation to use id for "for" attribute, per comment from David.


本文來自ChinaUnix博客,如果查看原文請(qǐng)點(diǎn):http://blog.chinaunix.net/u/16928/showart_2185626.html
您需要登錄后才可以回帖 登錄 | 注冊(cè)

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號(hào)-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號(hào):11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報(bào)專區(qū)
中國互聯(lián)網(wǎng)協(xié)會(huì)會(huì)員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請(qǐng)注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP