PHP类:ArrayAccess接口 - 是否可以直接在类中使用数组接口?

In PHP, I'm trying to access directly a class member (using the ArrayAccess interface) without having to create a new instance.

For example:

class my_class implements ArrayAccess {
    private static $d=array();
    function offsetGet($o){return self::$d[$o];}
    function offsetSet($o,$v){self::$d[$o]=$v;}
}
my_class['foo']='bar';//Syntax error
echo my_class['foo'];

All I want to know is if there is ANY way of making this happen without having to do $var=new my_class();

I don't want to do that unless it is EXTREMELY necessary and that there is no way around that syntax error.

I want to get rid of that syntax error, if possible.

I'm not 100% sure if it is possible (probably not), but better task than dying in doubt and never trying.

I'm using PHP 5.4.7 on Windows 8 Pro x64, running on a intel core2quad i586 2.63ghz (just in case).

Well, I see it is impossible, so, I really had to use new instances.

Here is the result:

error_reporting(E_ALL^E_STRICT);//removes the "Strict Standards" warning, don't do this
final class session implements ArrayAccess {
    //session data
    private static $s=null;

    //function (setters and getters)
    private static $f=array('s'=>array(),'g'=>array());//general setter/getter
    private $c=array('s'=>array(),'g'=>array());//private setter/getter

    function setter($k,$f=null)
    {
        if(($a=func_num_args())<=1)return!$a?false:((@$this)?(@$this->c['s'][$k]):(@self::$f['s'][$k]));
        else if($f==null){if(@$this)unset($this->c['s'][$k]);else unset(self::$f['s'][$k]);return true;}
        else return is_callable($f)&&(@$this?$this->c['s'][$k]=$f:self::$f['s'][$k]=$f);
    }

    function getter($k,$f=null)
    {
        if(($a=func_num_args())<=1)return!$a?false:((@$this)?(@$this->c['g'][$k]):(@self::$f['g'][$k]));
        else if($f==null){if(@$this)unset($this->c['g'][$k]);else unset(self::$f['g'][$k]);return true;}
        else return is_callable($f)&&(@$this?$this->c['g'][$k]=$f:self::$f['g'][$k]=$f);
    }

    //==== arrayaccess ====
    //extra: setters and getters implemented when accessing $session['offset']
    //       setter: gives the value, expects a value in return
    //       getter: gives the value, returns the value returned by the getter
    function offsetSet($o,$v){@self::$s[$o]=(@$this->c['s'][$o])?$this->c['s'][$o]($v,$o):(@self::$f['s'][$o]?call_user_func(self::$f['s'][$o],$v,$o):@self::$s[$o]);}
    function offsetExists($o){return isset(self::$s[$o]);}
    function offsetUnset($o){unset(self::$s[$o]);}
    function offsetGet($o){return(@$this->c['g'][$o])?$this->c['g'][$o](@self::$s[$o]):(@self::$f['g'][$o]?call_user_func(self::$f['g'][$o],@self::$s[$o]):@self::$s[$o]);}
    //==== arrayaccess ====
}

$s=new session();

$s->setter('test',function($ob){return$ob>6?'bigger than 6':'lower than 6';});

session::setter('test',function($st){return$st<5?'lower than 5':'bigger than 5';});
session::setter('test',null);//*deletes the setter,*/ session::setter('test');//return setter

$s['test']=5;

var_dump($s->setter('test'),session::setter('test'),$s['test']);
//expected output (php 5.3.0): object(Closure)#2 (1) { ["parameter"]=> array(1) { ["$ob"]=> string(10) "" } } NULL string(12) "lower than 6"

I know it look awful, but works as intended!

All data is shares across all new instances and all the setters in the general context are executed as expected.

If you want to use this code for you, remember this:

  • session::[sg]etter('test',null); is NOT the same as session::[sg]etter('test');!

  • The setter has 2 parameter (value and offset), while the getter only has 1 (the value);

  • Both the setter and getter MUST return a value!

In one of the comments I said this:

I have a setter method, and I believe it is impossible to do $class=new my_class(); $class->setter($param); and my_class::setter($param);

Well, it is not impossible, it just isn't standard (that's why the 1st line is error_reporting(E_ALL^E_STRICT);). Without this line, PHP goes crazy when you try to do session::setter('test');.