【问题标题】:PHP ArrayAccess set multidimensionalPHP ArrayAccess 设置多维
【发布时间】:2015-06-10 03:35:43
【问题描述】:

编辑:我意识到文字的数量可能令人生畏。这个问题的本质是:
如何实现 ArrayAccess 使得设置多维值成为可能?

 


 

我知道 here 已经讨论过这个问题,但我似乎无法正确实现 ArrayAccess 接口。

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

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

现在普遍的看法似乎是offsetGet() 方法必须通过引用返回(&amp;offsetGet())。但是,这并不能解决问题,恐怕我不知道如何正确实现该方法-为什么要使用 getter 方法来设置值? php doc here 也不是很有帮助。

要直接复制这个(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';

 


 

编辑 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);
    }
}

 

我将它用于我的 Config 库 libconfig,它在 MIT 许可下可在 Github 上使用。

【问题讨论】:

    标签: php arrays multidimensional-array arrayaccess


    【解决方案1】:

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

    【讨论】:

    • 嘿,非常感谢!我必须实现 getIterator 函数,但这很容易(更新了问题)。谢谢! :)
    猜你喜欢
    • 2015-01-22
    • 2015-02-17
    • 2014-03-16
    • 1970-01-01
    • 2012-07-05
    • 1970-01-01
    • 1970-01-01
    • 2022-01-08
    • 1970-01-01
    相关资源
    最近更新 更多