2011-05-09 20 views
5

想知道是否有可能像做以下的(我知道如预期的代码将无法正常工作,只是试图让整个目的):__set/__获取有关阵列属性

class Form 
{ 
    private $v = array(); 

    function __set($varName, $varValue) 
    { 
     ... do some treatment on the varValue ... 
     $this->v[$varName] = $varValue; 
    } 

    function &__get($varName) 
    { 
     if(!isset($this->v[$varName])) 
      $this->v[$varName] = NULL; 

     return $this->v[$varName]; 
    } 
}; 

我想可以设置一个变量,如:

$form->Values['whatever'] = 'dirty';

,并把它通过setter函数将调用一些清洁工作,并最终真正填补了其他几个阵列像“HtmlValues”和“SqlValues”,所以我跑可以拉取编码的值我想要的格式,这样我就可以再打

echo $form->HtmlValues['whatever'];

的问题当然是正常的问题,如果你只是用_ 得到的,你最终会设置所返回的值,即使& _get通过引用和事物类型的工作返回它,即使您正在设置私有成员,__set实际上也不会被调用。

所以基本上,我想知道如果有来电。只要你设置一个数组(可能是多个阵列深,中值的函数的方式有什么不一样$form->Values['group']['item'] = 'whatever';

所需的输出会是这样的:

$form->Values['name'] = "&"; 
echo $form->HtmlValues['name']; = & 

(只是要加强,我不是在寻找实际的编码,只需调用它,因为它的设置每个变量的能力/改变,而不必手动整个数组编码)

回答

3

你要实现ArrayAccess接口。链接的页面有如何做到这一点的例子。

编辑:为了便于操作,我已经包括了从下面php.net的例子:

<?php 
class obj implements arrayaccess { 
    private $container = array(); 
    public function __construct() { 
     $this->container = array(
      "one" => 1, 
      "two" => 2, 
      "three" => 3, 
     ); 
    } 
    public function offsetSet($offset, $value) { 
     if (is_null($offset)) { 
      $this->container[] = $value; 
     } else { 
      $this->container[$offset] = $value; 
     } 
    } 
    public function offsetExists($offset) { 
     return isset($this->container[$offset]); 
    } 
    public function offsetUnset($offset) { 
     unset($this->container[$offset]); 
    } 
    public function offsetGet($offset) { 
     return isset($this->container[$offset]) ? $this->container[$offset] : null; 
    } 
} 

$obj = new obj; 

var_dump(isset($obj["two"])); 
var_dump($obj["two"]); 
unset($obj["two"]); 
var_dump(isset($obj["two"])); 
$obj["two"] = "A value"; 
var_dump($obj["two"]); 
$obj[] = 'Append 1'; 
$obj[] = 'Append 2'; 
$obj[] = 'Append 3'; 
print_r($obj); 
?> 
+0

真棒,使我在正确的方向:) – John 2011-05-09 19:44:57

0

我在这种情况下做的是让__get()返回一个对象,该对象不是直接返回数组,而是ArrayObject

private $v; 
public function __construct() 
{ 
    $this->v = new ArrayObject(); // or MyArrayObject() 
    // repeat for each of your "arrays" you want to return 
} 

(请注意,这是由父类,这也可能是有用的,其它情况下直接实现ArrayAccess不同。)

下面是一个例子:

<?php 
class MyArrayObject extends ArrayObject 
{ 
    private $validate; 
    public function __construct($validate) 
    { 
    parent::__construct(); 
    $this->validate = $validate; 
    } 

    public function offsetSet($i, $v) 
    { 
    $validate = $this->validate; 
    if (!$validate($this, $i, $v)) 
     throw new Exception(); 

    parent::offsetSet($i, $v); 
    } 
} 

class Foo 
{ 
    private $v; 
    public function __construct() 
    { 
    $this->v = new MyArrayObject(function(MyArrayObject $me, $i, $v) { 
     // only accept values that are larger than 5 
     return $v > 5; 
    }); 
    } 

    public function __get($key) 
    { 
    if ($key == 'bar') return $this->v; 
    } 
} 

$f = new Foo(); 
$f->bar[] = 10; 
$f->bar[] = 5; // throws exception