PHP ArrayAccess设置为多维


PHP ArrayAccess set multidimensional

编辑:我意识到文本的数量可能很吓人。这个问题的本质:
如何以一种可以设置多维值的方式实现ArrayAccess

 


 

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

基本上,我有一个类来处理带有数组的应用程序配置,并实现了ArrayAccess。检索值可以很好地工作,甚至可以从嵌套键($port = $config['app']['port'];)中检索值。设置值仅适用于一维数组:当我尝试(取消)设置值(例如,上一个示例中的端口)时,我会收到以下错误消息:

Notice:  Indirect modification of overloaded element <object name> has no effect in <file> on <line>

现在的普遍观点似乎是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';

 


 

EDIT 2:正如Ryan所指出的,解决方案是使用ArrayObject(它已经实现了ArrayAccessCountableIteratorAggregate
要将其应用于持有数组的类,请将其结构如下:

<?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);
    }
}

 

我将其用于我的配置库libconfig,该库可在Github上获得MIT许可。

我不确定这是否有用。我注意到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']);

输出:

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)