只读多维数组属性,PHP

|| 我一直在和
ArrayAccess
和PHP \'s magic(
__get
__set
)混蛋,我被困住了。 我正在尝试实现一个类,其中某些属性(即数组)是只读的。它们将最初由构造函数设置,但此后不得修改。 通过引用使用
__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
(根据我的示例),但是我需要知道这是写操作,而不是读操作。 我已经一半接受了这一目标,但我仍然充满希望。有谁知道我要完成的目标吗? 我正在考虑使用ѭ0的一些可能的解决方法,但据我所知,假设我将使用调用ѭ1的属性符号,那么我将回到这个位置。 更新:Another0ѭ又是有趣的一天。 (这是一个不同的问题,但是我想它可以使用。仅用于踢球。)
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]);
    }

}
    
已邀请:
        您需要使用实现implementing0ѭ的第二个类来代替数组。然后,您将可以使用
offsetSet()
方法控制添加到数组的内容:
class ReadOnlyArray implements ArrayAccess {
    private $container = array();
    public function __construct(array $array) {
        $this->container = $array;
    }
    public function offsetSet($offset, $value) {
        throw new Exception(\'Read-only\');
    }
    public function offsetExists($offset) {
        return isset($this->container[$offset]);
    }
    public function offsetUnset($offset) {
        unset($this->container[$offset]);
    }
    public function offsetGet($offset) {
        if (! array_key_exists($offset, $this->container)) {
            throw new Exception(\'Undefined offset\');
        }
        return $this->container[$offset];
    }
}
然后可以用原始数组初始化
ReadOnlyArray
$readOnlyArray = new ReadOnlyArray(array(\'foo\', \'bar\'));
    
        您不能通过ref返回,这将解决可更改性问题,但不允许更改允许更改的某些值。 另外,您也需要将每个返回的数组都包装在ArrayAccess中-并禁止在那里进行写访问。     

要回复问题请先登录注册