2014-02-04 1 views
2

В 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.63ghz (на всякий случай).

+0

И почему вы не можете просто использовать массив? – PeeHaa

+0

Потому что я хочу выполнять другие задачи, такие как запуск функций и добавление геттеров и сеттеров. Кроме того, я хочу сохранить все статичным и не иметь экземпляров, которые просто получают или устанавливают значения родительскому статическому классу. Тогда мне придется создавать статические и нестатические элементы в одном классе с тем же именем, что невозможно и абсурдно. –

+0

«Тогда мне пришлось бы создавать статические и нестатические члены в том же классе с тем же именем». Общепринятой практикой является создание основанного на «Пакете» подхода к этому.В принципе у вас есть класс, который может быть создан и представляет объект (либо из хранилища, либо иначе), а затем у вас есть класс, который имеет возможность манипулировать несколькими объектами. В доктрине они известны как классы таблиц, в Propel, одноранговые классы. При таком подходе вы можете отделить переменные-члены либо привязать их к реальному объекту, либо к классу «Пакет». –

ответ

0

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

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

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 (значение);

  • И сеттер и геттер ДОЛЖНЫ вернуть значение!

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

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

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

+1

Существует отличная цитата из первого парка юрского периода: «Вы были так заняты, беспокоясь о том, можете ли вы, вы не переставали думать о том, должны ли вы». Просто тот факт, что вам нужно отказаться от строгих стандартов, чтобы избежать безумства php, должен быть красным флагом, что это не правильный подход. Этот код не только с точки зрения ремонтопригодности, но и с его профилированием? Мне любопытно, если все эти анонимные вызовы функций быстрее, то же или медленнее, чем вызов конкретных функций. –

+0

Я не беспокоюсь о том, чтобы быть супер-быстрым или чем-то еще. Я просто хочу, чтобы это было простое использование, а не просто сделать и запустить. Я так же оптимизирован, насколько это возможно, по моему честному мнению (за исключением ошибок, подавляющих (@) инструкции везде, вместо использования 'isset()'). Я упомянул, что строгое предупреждение - это когда я получаю доступ к 'session :: [gs] etter()' вместо 'session -> [gs] etter()'. –

Смежные вопросы