我一直在欺騙與ArrayAccess
和PHP的魔術(__get
,__set
)一段時間了,和我被困。只讀多維數組屬性,PHP
我想實現一個類,其中一些屬性,它是數組,只讀。它們最初將由構造函數設置,但此後不應修改。
通過引用使用__get
魔術,我可以訪問屬性中任意深度的數組元素,並且我認爲當這些屬性通過__set
定位時,我可以拋出異常。
問題是,當我訪問一個數組元素的值時,PHP正在調用__get
來通過引用返回該數組的部分,並且我不知道它是否具有讀或寫操作。
(最糟糕的是我知道這將在,但已經與ArrayAccess
作爲可能的解決方法解決嘴硬,給出的性能是一個實現對象的實例)
簡單的例子:
class Test{
public function &__get($key){
echo "[READ:{$key}]\n";
}
public function __set($key, $value){
echo "[WRITE:{$key}={$value}]\n";
}
}
$test = new Test;
$test->foo;
$test->foo = 'bar';
$test->foo['bar'];
$test->foo['bar'] = 'zip';
和輸出:
[READ:foo]
[WRITE:foo=bar]
[READ:foo]
[READ:foo] // here's the problem
實際上,我只需要值foo
(,按照我的示例),但我需要知道這是一個寫操作,而不是讀取。
我已經接受了一半,這是無法實現的,但我仍然充滿希望。有沒有人知道我想要完成的工作?
我正在考慮與ArrayAccess
一些可能的解決方法,但據我所知,由於我要使用調用__get
的屬性表示法,因此我最終會回到這個位置。
更新:另一個有趣的一天ArrayAccess
。
(這是一個不同的問題,但我想它在。發帖只是踢。)
class Mf_Params implements ArrayAccess{
private $_key = null;
private $_parent = null;
private $_data = array();
private $_temp = array();
public function __construct(Array $data = array(), $key = null, self $parent = null){
$this->_parent = $parent;
$this->_key = $key;
foreach($data as $key => $value){
$this->_data[$key] = is_array($value)
? new self($value, $key, $this)
: $value;
}
}
public function toArray(){
$array = array();
foreach($this->_data as $key => $value){
$array[$key] = $value instanceof self
? $value->toArray()
: $value;
}
return $array;
}
public function offsetGet($offset){
if(isset($this->_data[$offset])){
return $this->_data[$offset];
}
// if offset not exist return temp instance
return $this->_temp[$offset] = new self(array(), $offset, $this);
}
public function offsetSet($offset, $value){
$child = $this;
// copy temp instances to data after array reference chain
while(!is_null($parent = $child->_parent) && $parent->_temp[$child->_key] === $child){
$parent->_data[$child->_key] = $parent->_temp[$child->_key];
$child = $parent;
}
// drop temp
foreach($child->_temp as &$temp){
unset($temp);
}
if(is_null($offset)){
$this->_data[] = is_array($value)
? new self($value, null, $this)
: $value;
}else{
$this->_data[$offset] = is_array($value)
? new self($value, $offset, $this)
: $value;
}
}
public function offsetExists($offset){
return isset($this->_data[$offset]);
}
public function offsetUnset($offset){
unset($this->_data[$offset]);
}
}
謝謝** Benjamin Morel **;正如我提到** cweiske **,我想;我開始認爲PHP對象引擎需要被審查;像這樣的實例,以及缺少對'&offsetGet()'的支持都非常令人沮喪。 – Dan 2011-06-13 06:38:37
感謝您的更新;我讚賞代碼建議。正如我在** cweiske **的評論中所提到的,我也一直在'ArrayAccess'上掙扎,但出於不同的原因。我放棄了對ArrayAccess失敗的嘗試,但檢查我的問題更新以查看它。 – Dan 2011-06-13 06:43:04
不太清楚如果你不告訴我們你對它的期望是什麼,什麼不工作,你的實現有什麼問題: – Benjamin 2011-06-13 06:45:54