正确扩展PHP中的ArrayObject?

Ind*_*ial 7 php arrays oop spl arrayobject

问题:我正在尝试扩展PHP ArrayObject,如下所示.不幸的是,我无法在设置多维对象时使其正常工作,而是因为我在PHP中启用了严格设置而引发错误.(Error: Strict standards: Creating default object from empty value)

问题:如何修改我的课程以自动为我创建不存在的级别?

代码:

$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);
    }
}
Run Code Online (Sandbox Code Playgroud)

nic*_*083 13

更深入地了解您的问题,您可以创建一个模拟多维对象概念的类.

我发布的解决方案并没有延伸ArrayObject到你提到的目标.当您将问题标记为oop时,我认为重要的是加强分离存储对象状态的方式与如何访问它.

希望这能帮助您实现您的需求!

根据你的说法,多维对象是:

  • 处理多级嵌套信息
  • 它是通过属性提供对信息的读/写访问来实现的
  • 访问未定义的属性时表现很好.这意味着,例如,你做一个空的实例如下:$config->database->host = 'localhost'在database和host电平自动初始化,并且host将返回'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);
    }
}
Run Code Online (Sandbox Code Playgroud)

演示

代码:var_dump(new MultiDimensionalObject());

结果:

object(MultiDimensionalObject)[1]
    private 'properties' => 
        array
            empty
Run Code Online (Sandbox Code Playgroud)

码:

$data = array( 'database' => array ( 'host' => 'localhost' ) );
$config = new MultiDimensionalObject($data);        
var_dump($config->database);
Run Code Online (Sandbox Code Playgroud)

结果:

object(MultiDimensionalObject)[2]
    private 'properties' => 
        array
            'host' => string 'localhost' (length=9)
Run Code Online (Sandbox Code Playgroud)

码:

$config->database->credentials->username = "admin";
$config->database->credentials->password = "pass";
var_dump($config->database->credentials);
Run Code Online (Sandbox Code Playgroud)

结果:

object(MultiDimensionalObject)[3]
    private 'properties' => 
        array
          'username' => string 'admin' (length=5)
          'password' => string 'pass' (length=4)
Run Code Online (Sandbox Code Playgroud)

码:

$config->database->credentials->username;
Run Code Online (Sandbox Code Playgroud)

结果:

admin
Run Code Online (Sandbox Code Playgroud)