編集:テキストの量が威圧的かもしれないことに気付きました. この質問の本質:
多次元値の設定を可能にする方法で ArrayAccess を実装する方法は?
これについてはすでにここで説明されていることは承知していますが、ArrayAccess インターフェイスを正しく実装できないようです。
基本的に、配列と実装されたアプリ構成を処理するクラスがありますArrayAccess
。ネストされたキー ( ) からの値でも、値の取得は正常に機能します$port = $config['app']['port'];
。ただし、値の設定は 1 次元配列に対してのみ機能します。値 (前の例のポートなど) を設定 (解除) しようとするとすぐに、次のエラー メッセージが表示されます。
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 を使用することでした (これは既にArrayAccess
、Countable
および を実装していますIteratorAggregate
)。
配列を保持するクラスに適用するには、次のように構成します。
<?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);
}
}
これは、MIT ライセンスの下でGithublibconfig
で利用できる構成ライブラリに使用しました。