PHP ArrayAccess 设置多维

Mor*_*ich 3 php arrays multidimensional-array arrayaccess

编辑:我意识到文本量可能令人生畏。这个问题的本质是:
如何以能够设置多维值的方式实现ArrayAccess?

 


 

我知道这已经在这里讨论过,但我似乎无法正确实现 ArrayAccess 接口。

基本上,我有一个类来处理带有数组和实现的应用程序配置ArrayAccess。检索值工作正常,甚至是来自嵌套键 ( ) 的值$port = $config['app']['port'];。不过,设置值仅适用于一维数组:一旦我尝试设置(取消)设置一个值(例如上一个示例中的端口),我就会收到以下错误消息:

Notice:  Indirect modification of overloaded element <object name> has no effect in <file> on <line>
Run Code Online (Sandbox Code Playgroud)

现在普遍的观点似乎是该offsetGet()方法必须通过引用返回(&offsetGet())。然而,这并不能解决问题,而且我担心我不知道如何正确实现该方法 - 为什么使用 getter 方法来设置值?这里的php 文档也没有太大帮助。

要直接复制此内容(PHP 5.4-5.6),请查找下面附加的示例代码:

<?php

class Config implements \ArrayAccess
{

    private $data = array();

    public function __construct($data)
    {
        $this->data = $data;
    }


    /**
     * ArrayAccess Interface
     * 
     */
    public function offsetSet($offset, $value)
    {
        if (is_null($offset)) {
            $this->data[] = $value;
        } else {
            $this->data[$offset] = $value;
        }
    }

    public function &offsetGet($offset)
    {       
        return isset($this->data[$offset]) ? $this->data[$offset] : null;
    }

    public function offsetExists($offset)
    {
        return isset($this->data[$offset]);
    }

    public function offsetUnset($offset)
    {
        unset($this->data[$offset]);
    }
}

$conf = new Config(array('a' => 'foo', 'b' => 'bar', 'c' => array('sub' => 'baz')));
$conf['c']['sub'] = 'notbaz';
Run Code Online (Sandbox Code Playgroud)

 


 

编辑2:正如 Ryan 指出的那样,解决方案是使用 ArrayObject 代替(它已经实现了ArrayAccess,CountableIteratorAggregate)。
要将其应用于保存数组的类,请像这样构造它:

<?php

class Config extends \ArrayObject
{

    private $data = array();

    public function __construct($data)
    {
        $this->data = $data;
        parent::__construct($this->data);
    }


    /**
     * Iterator Interface
     *
     */
    public function getIterator() {
        return new \ArrayIterator($this->data);
    }

    /**
     * Count Interface
     *
     */
    public function count()
    {
        return count($this->data);
    }
}
Run Code Online (Sandbox Code Playgroud)

 

我将其用于我的 Config 库,libconfig该库可在 MIT 许可证下在Github上获取。

Rya*_*ent 5

我不确定这是否有用。我注意到这ArrayObject门课很“有趣”......

我不确定这是否是一个“答案”。这更多的是对这个班级的观察。

它按照标准正确处理“多维数组”内容。

您也许可以添加方法来让它做更多您想要的事情?

<?php //

class Config extends \ArrayObject
{

//    private $data = array();

    public function __construct(array $data = array())
    {
        parent::__construct($data);
    }
}

$conf = new Config(array('a' => 'foo', 'b' => 'bar', 'c' => array('sub' => 'baz')));
$conf['c']['sub'] = 'notbaz';
$conf['c']['sub2'] = 'notbaz2';

var_dump($conf, $conf['c'], $conf['c']['sub']);

unset($conf['c']['sub']);

var_dump('isset?: ', isset($conf['c']['sub']));

var_dump($conf, $conf['c'], $conf['c']['sub2']);
Run Code Online (Sandbox Code Playgroud)

输出:

object(Config)[1]
  public 'a' => string 'foo' (length=3)
  public 'b' => string 'bar' (length=3)
  public 'c' => 
    array
      'sub' => string 'notbaz' (length=6)
      'sub2' => string 'notbaz2' (length=7)

array
  'sub' => string 'notbaz' (length=6)
  'sub2' => string 'notbaz2' (length=7)

string 'notbaz' (length=6)

string 'isset?: ' (length=8)

boolean false

object(Config)[1]
  public 'a' => string 'foo' (length=3)
  public 'b' => string 'bar' (length=3)
  public 'c' => 
    array
      'sub2' => string 'notbaz2' (length=7)

array
  'sub2' => string 'notbaz2' (length=7)

string 'notbaz2' (length=7)
Run Code Online (Sandbox Code Playgroud)