更新:我遇到了ArrayObject
解决方案的问题,因为PHP5.2.0(现已修复)与empty的交互存在一个错误()
和isset()
与ARRAY_AS_PROPS
标志一起使用时。我尝试了一些修复,但最终我的朋友Mike指出了我遗漏的一些东西:从PHP5.1开始,设置未定义的公共属性不再引发E_STRICT
通知。了解这一点后,您现在可以执行以下操作而不会引发任何错误:
class Foo { public function __set($key, $value) { $this->$key = $value; } } $foo = new Foo(); $foo->bar = array(); $foo->bar[] = 42;
这是一个更简单的解决方案,性能更好,并且解决了我遇到的所有问题。谢谢,迈克!
几周前,有人报告了一个针对Zend_View的错误,这让我一开始很困惑。基本上,以下内容现在在PHP5.2.0中失败了:
$view->foo = array(); $view->foo[] = 42;
出现了一条通知,“注意:间接修改重载属性Zend_View::$foo无效。”
几个月前我在php内部列表上读到过这个,但当时还不明白后果。基本上,__get()
不再以读取模式返回引用和返回值,这使得使用传统方法无法使用重载修改数组。
DerickRethans在8月份的博客中谈到了这个问题。他的解决方案是在__get()
中使用switch()
语句将返回值显式转换为数组:
public function __get($key) { if (is_array($this->_vars[$key])) { return (array) $this->_vars[$key]; } return $this->_vars[$key]; }
这种方法的问题是您随后会遇到其他数组功能的问题,例如通过引用分配。
经过一些工作后,我发现最好的解决方案是让类扩展ArrayObject
,但稍作改动:
class My_Class extends ArrayObject { public function __construct($config = array()) { // ... some setup // Allow accessing properties as either array keys or object properties: parent::__construct(array(), ArrayObject::ARRAY_AS_PROPS); } }
这种组合允许对对象中的属性进行一些非常灵活的访问:
// from the original example: $view->foo = array(); $view->foo[] = 42; echo $view['foo'][0]; // '42' echo $view->foo[0]; // same
在Zend_View
中始终难以处理的一个问题是将“公共”属性(模板变量)与私有/受保护属性(如助手、过滤器和脚本路径)分开。由于这些属性是在类中预先声明的,ArrayObject::ARRAY_AS_PROPS
设置可防止发生任何此类冲突,并有助于简化代码。
故事的寓意?如果您需要能够修改类中的重载数组并支持PHP5.2.0,请扩展ArrayObject
。