__set / __获取数组属性

时间:2011-05-09 16:19:53

标签: php

想知道是否可以执行以下操作(我知道代码不会按预期工作,只是试图达到目的):

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,你最终会设置一个返回的值,即使& _get通过引用返回它,并且是即使您正在设置私有成员,也不会实际调用__set。

所以基本上,我想知道是否有办法在数组中设置函数时调用一个函数(可能是多个数组深,哪些不喜欢$form->Values['group']['item'] = 'whatever';

所需的输出类似于:

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

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

3 个答案:

答案 0 :(得分:4)

您想要实现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);
?>

答案 1 :(得分:1)

看看ArrayAccess

答案 2 :(得分: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