2009年2月22日星期日

Re: [fw-mvc] Zend_Form_Element::getAttribs()

-- Piotr Kabaciński <kabot@seo.pl> wrote
(on Sunday, 22 February 2009, 09:51 PM +0100):
> I wonder why all attributes are kept like common object attribute and
> why methods like get/setAttrib operate on $this->$name.
>
> Wasn't it faster if there is array eg. $this->attributes and every
> operation on attribute will be simple get $this->attributes[$name]?

You're forgetting that get/setAttrib() are not the only way to affect
these attributes: the primary API is to use overloading.

The solution you present may be faster when you want to get at all
attributes at once (a micro-optimization at best), but not when you want
to retrieve a single attribute -- if you use overloading, it will
actually be faster, as you'll be grabbing a public property.

However, the rationale is actually something a little less trivial:
overloading to arrays is problematic in PHP.

When I say arrays here, I'm not talking about storing the various
attributes in a protected $_attributes array; I'm talking about if one
of those values is an array.

The situation presents itself when you want to add new members to an
array value, either through [] notation or using an explicit key. As an
example, try the following:

class Foo
{
protected $_attribs = array();

public function __get($name)
{
if (isset($this->_attribs[$name])) {
return $this->_attribs[$name];
}

return null;
}

public function __set($name, $value)
{
$this->_attribs[$name] = $value;
}
}

$o = new Foo;
$o->foo = array();

Now, try either of the following two lines:

$o->foo[] = 'bar';
$o->foo['bar'] = 'bar';

What you'll get is a PHP notice:

Indirect modification of overloaded property Foo::$foo has no effect

The interesting part? if you use public properties -- which, of course,
never trigger __get() -- there are no issues, a situation we discovered
when we ran into the same issue in Zend_View. Since we wanted a similar
API for Zend_Form (in part to remain internally consistent in the
framework), we had to use a similar solution.

The other way around it is to not use overloading. But I personally feel
that makes the API less elegant.

> Adventage for this soulution is that when you want to get attributes
> list you could just return $this->$attributes and it is much faster than
> get_object_vars($this) and then unset every variable that starts with
> underline.
> Maybe i pass over something but running code through xdebug emphasize
> method getAttribs and time spending on this method could be
> insignificant using array.
>

--
Matthew Weier O'Phinney
Software Architect | matthew@zend.com
Zend Framework | http://framework.zend.com/

没有评论: