采取面向对象编程的视角,可以创建一个类来模拟多维对象的概念。
我发布的解决方案并不是通过扩展`ArrayObject`来实现您提到的目标。由于您将问题标记为面向对象编程,因此我认为强调将存储对象状态的方式与访问它的方式分开很重要。
希望这将有助于您实现所需的功能!
从您的说法中,多维对象是指:
- 处理多个嵌套信息级别
- 通过属性提供读/写访问信息
- 当访问未定义的属性时表现良好。这意味着,例如,在空实例上执行以下操作:
$config->database->host = 'localhost'
自动初始化
database
和
host
级别,并在查询时返回
'localhost'
。
- 理想情况下,应从关联数组中进行初始化(因为您已经可以将配置文件解析为它们)。
建议的解决方案是怎样实现这些特性的?
第二个特性很容易实现:使用PHP的
__get
和
__set
方法。每当对不可访问属性(即未在对象中定义的属性)进行读取/写入时,就会调用它们。然后需要的技巧是不声明任何属性,并通过这些方法处理属性操作,将被访问的属性名映射为用作存储的关联数组的键。它们基本上提供了访问内部存储信息的接口。
对于第三个特性,我们需要一种方法在读取未声明属性时创建一个新的嵌套级别。关键点是意识到返回的属性值必须是一个多维对象,因此还可以从中创建进一步的嵌套级别:每当我们要求一个在内部数组中不存在名称的属性时,就会将那个名称与
MultiDimensionalObject
的新实例关联起来并返回它。返回的对象也能够处理已定义或未定义的属性。
当写入未声明属性时,我们只需将其名称与提供的值分配给内部数组即可。
第四个特性很容易(请查看
__construct
实现)。我们只需要确保在属性的值为数组时创建一个
MultiDimensionalObject
即可。
最后一个特性:我们处理第二和第三个特性的方式允许我们在任何嵌套级别中读取和写入属性(已声明和未声明)。您可以在空实例上执行像
$config->foo->bar->baz = 'hello'
这样的操作,然后成功查询
$config->foo->bar->baz
。
重要
请注意,MultiDimensionalObject
不是一个数组,而是由一个数组构成的,可以根据需要更改对象状态的存储方式。
实现
class MultiDimensionalObject {
private $properties;
public function __construct($properties = array()) {
$this->properties = array();
$this->populate($properties);
}
private function populate($properties) {
foreach($properties as $name => $value) {
$this->create_property($name, $value);
}
}
private function create_property($name, $value) {
$this->properties[$name] = is_array($value) ? $this->create_complex_property($value)
: $this->create_simple_property($value);
}
private function create_complex_property($value = array()){
return new MultiDimensionalObject($value);
}
private function create_simple_property($value) {
return $value;
}
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
Config
类成为ArrayObject
的一个特化实现吗?或者你只是因为它提供的信息存储功能而需要这样做? - nick2083ArrayObject
实现:https://dev59.com/lVrUa4cB1Zd3GeqPl6n4 - Industrial