代码:
$config = new Config; $config->lvl1_0 = true; // Works $config->lvl1_1->lvl2 = true; // Throws error as "lvl1" isn't set already class Config extends ArrayObject { function __construct() { parent::__construct(array(),self::ARRAY_AS_PROPS); } public function offsetSet($k,$v) { $v = is_array($v) ? new self($v) : $v; return parent::offsetSet($k,$v); } }
解决方案即时发布不会从ArrayObject扩展到您提到的目标.当您将问题标记为oop时,我认为重要的是加强分离,即存储对象状态的方式与如何访问它.
希望这能帮助您实现您的需求!
根据你的说法,多维对象是:
>处理多级嵌套信息
>它通过提供对属性的信息的读/写访问来实现
>访问未定义的属性时表现良好.这意味着,例如,您在空实例上执行以下操作:$config-> database-> host =’localhost’自动初始化数据库和主机级别,主机在查询时将返回“localhost”.
>理想情况下,将从关联数组初始化(因为您已经可以将配置文件解析为它们)
提出的解决方案
那么,这些功能如何实现呢?
第二个很简单:使用PHP的__get和__set方法.只要在不可用的属性(未在对象中定义的属性)上进行读/写操作,就会调用这些对象.
然后诀窍就是不通过这些方法声明任何属性和处理属性的操作,并将属性名称beign以作为关键字映射到用作存储的assosiative数组.它们基本上提供了用于访问内部存储的信息的接口.
对于第三个,我们需要一种方法来在重新声明未声明的属性时创建新的嵌套级别.
这里的关键点是要意识到属性的返回值必须是一个多维对象,因此可以从中创建更多的嵌套级别:每当我们要求内部数组中不存在其名称的属性时,我们将该名称与MultiDimensionalObject的新实例相关联并返回它.返回的对象也能够处理已定义或未定义的属性.
当写入未声明的属性时,我们所要做的就是使用内部数组中提供的值指定它的名称.
第四个很容易(在__construct实现上看到它).我们必须确保在属性的值是数组时创建MultiDimensionalObject.
最后,第一个:我们处理第二个和第三个特征的方式允许我们在任何嵌套级别读取和写入属性(声明和未声明).
您可以在空实例上执行$config-> foo-> bar-> baz =’hello’等操作,然后成功查询$config-> foo-> bar-> baz.
重要
请注意,MultiDimensionalObject而不是beign本身是一个数组,它由一个数组组成,让您可以根据需要更改存储对象状态的方式.
履行
/* Provides an easy to use interface for reading/writing associative array based information */ /* by exposing properties that represents each key of the array */ class MultiDimensionalObject { /* Keeps the state of each property */ private $properties; /* Creates a new MultiDimensionalObject instance initialized with $properties */ public function __construct($properties = array()) { $this->properties = array(); $this->populate($properties); } /* Creates properties for this instance whose names/contents are defined by the keys/values in the $properties associative array */ private function populate($properties) { foreach($properties as $name => $value) { $this->create_property($name,$value); } } /* Creates a new property or overrides an existing one using $name as property name and $value as its value */ private function create_property($name,$value) { $this->properties[$name] = is_array($value) ? $this->create_complex_property($value) : $this->create_simple_property($value); } /* Creates a new complex property. Complex properties are created from arrays and are represented by instances of MultiDimensionalObject */ private function create_complex_property($value = array()){ return new MultiDimensionalObject($value); } /* Creates a simple property. Simple properties are the ones that are not arrays: they can be strings,bools,objects,etc. */ private function create_simple_property($value) { return $value; } /* Gets the value of the property named $name */ /* If $name does not exists,it is initilialized with an empty instance of MultiDimensionalObject before returning it */ /* By using this technique,we can initialize nested properties even if the path to them don't exist */ /* I.e.: $config->foo - property doesn't exists,it is initialized to an instance of MultiDimensionalObject and returned $config->foo->bar = "hello"; - as explained before,doesn't exists,it is initialized to an instance of MultiDimensionalObject and returned. - when set to "hello"; bar becomes a string (it is no longer an MultiDimensionalObject instance) */ public function __get($name) { $this->create_property_if_not_exists($name); return $this->properties[$name]; } private function create_property_if_not_exists($name) { if (array_key_exists($name,$this->properties)) return; $this->create_property($name,array()); } public function __set($name,$value) { $this->create_property($name,$value); } }
演示
码:
var_dump(new MultiDimensionalObject());
结果:
object(MultiDimensionalObject)[1] private 'properties' => array empty
码:
$data = array( 'database' => array ( 'host' => 'localhost' ) ); $config = new MultiDimensionalObject($data); var_dump($config->database);
结果:
object(MultiDimensionalObject)[2] private 'properties' => array 'host' => string 'localhost' (length=9)
码:
$config->database->credentials->username = "admin"; $config->database->credentials->password = "pass"; var_dump($config->database->credentials);
结果:
object(MultiDimensionalObject)[3] private 'properties' => array 'username' => string 'admin' (length=5) 'password' => string 'pass' (length=4)
码:
$config->database->credentials->username;
结果:
admin