Классы PHP: интерфейс ArrayAccess - возможно ли использовать интерфейс массива непосредственно в классе?

В PHP я пытаюсь получить прямой доступ к члену класса (используя интерфейс ArrayAccess) без необходимости создания нового экземпляра.

Например:

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'];

Все, что я хочу знать, есть ли ЛЮБОЙ способ сделать это без необходимости делать $var=new my_class();

Я не хочу этого делать, если это НЕ ЧРЕЗВЫЧАЙНО необходимо и что нет никакой возможности обойти эту синтаксическую ошибку.

Я хочу избавиться от этой синтаксической ошибки, если это возможно.

Я не уверен на 100%, если это возможно (вероятно, нет), но лучше, чем умереть в сомнениях и никогда не пытаться.

Я использую PHP 5.4.7 на Windows 8 Pro x64, работающем на Intel Core2quad i586 2,63 ГГц (на всякий случай).

1 ответ

Ну, я вижу, что это невозможно, поэтому мне действительно пришлось использовать новые экземпляры.

Вот результат:

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"

Я знаю, это выглядит ужасно, но работает как задумано!

Все данные являются общими для всех новых экземпляров, и все установщики в общем контексте выполняются, как ожидается.

Если вы хотите использовать этот код для себя, запомните это:

  • session::[sg]etter('test',null); это не то же самое, что session::[sg]etter('test');!

  • Установщик имеет 2 параметра (значение и смещение), а получатель имеет только 1 (значение);

  • И установщик, и получатель ДОЛЖНЫ возвращать значение!

В одном из комментариев я сказал это:

У меня есть метод установки, и я считаю, что это невозможно сделать $class=new my_class(); $ Class-> сеттер ($ пары); и my_class:: setter($param);

Ну, это не невозможно, это просто не стандартно (вот почему 1-я строка error_reporting(E_ALL^E_STRICT);). Без этой строки PHP сходит с ума, когда вы пытаетесь сделать session::setter('test');,

Другие вопросы по тегам