Модераторы: skyboy, MoLeX, Aliance, ksnk

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Событие при изменении атрибута объекта 
:(
    Опции темы
ShamanVoodoo
Дата 1.6.2013, 18:43 (ссылка)   | (голосов:4) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 17.10.2007
Где: Сергиев Посад

Репутация: -1
Всего: -3



упрощенный пример:
Код

class Controller
{
    protected $_var = array();
    
    // содержит код сохранения переменной $_var
    // например в БД
    public function save(){}
    
    public function action()
    {
        $var['test'] = 'blabla';
    }
    
    public function __set($key, $val)
    {
        if ($key == 'var')
        {
            $_var = $val;
            $this->save();
        }
    }
}

т.е.  задаем(и сохраняем) атрибут через __set 
проблема в том, что $_var ($var) должна работать как массив, а при таком варианте возникает ошибка
как реализовать подобный вариант(когда-то пробовал через ArrayObject, но не получилось)
и вообще есть ли какой-то способ отлавливать вызов методов и изменение атрибутов также как и с ошибочными вариантами?
PM MAIL ICQ   Вверх
Arantir
Дата 1.6.2013, 18:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Рыбак без удочки
**


Профиль
Группа: Участник
Сообщений: 960
Регистрация: 18.11.2012

Репутация: 2
Всего: 55



На вид какая-то странная смесь модели и контроллера. Может в этом проблема (в неправильном подходе/архитектуре)?

Почему не сделать вот так
Код

$_var[] = $val;
?


--------------------
interface Жопа {
    // ATTENTION: has to be implemented by every class of the project for proper project work
}
PM   Вверх
ShamanVoodoo
Дата 1.6.2013, 19:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 17.10.2007
Где: Сергиев Посад

Репутация: -1
Всего: -3



Цитата(Arantir @  1.6.2013,  18:50 Найти цитируемый пост)
На вид какая-то странная смесь модели и контроллера. Может в этом проблема (в неправильном подходе/архитектуре)?

по поводу кода это просто пример и mvc тут ни при чем. не несите чушь

Цитата(Arantir @  1.6.2013,  18:50 Найти цитируемый пост)
Почему не сделать вот так

где именно?
PM MAIL ICQ   Вверх
awdev
Дата 2.6.2013, 20:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 22.11.2009

Репутация: нет
Всего: 1



Код


class Controller
{
    protected $_vars = array();
    protected function save(){
        echo "Saving...".print_r($this->_vars,true).PHP_EOL;
    }
    public function __call($name, $args){
        echo "CALL: $name".PHP_EOL;
        $this->$name($args);
    }
    public function __get($key){    
        echo "Get $key".PHP_EOL;
        if(isset($this->_vars[$key]))
            return $this->_vars[$key];
        else
            return NULL;
    }
    public function __set($key, $value){
        echo "Set $key=$value".PHP_EOL;
        $this->_vars[$key] = $value;
        $this->save();
    }
}

class Child extends Controller{    
    protected function foo($args){    
        var_dump($args);
    }
}
$c = new Child;
$c->a=2;
echo "A is: ".$c->a.PHP_EOL;
$c->foo("test");


Результат:
Цитата


Set a=2
Saving...Array
(
    [a] => 2
)

Get a
A is: 2
CALL: foo
array(1) {
  [0]=>
  string(4) "test"
}


PM MAIL   Вверх
ShamanVoodoo
Дата 2.6.2013, 21:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 17.10.2007
Где: Сергиев Посад

Репутация: -1
Всего: -3



awdev пасиб за старания, но это не то:  представь, что кроме $_vars еще 10 таких атрибутов, кроме этого атрибут должен работать как массив т.е. $c->a[4]=2;
PM MAIL ICQ   Вверх
krundetz
Дата 3.6.2013, 09:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вечный странник
***


Профиль
Группа: Завсегдатай
Сообщений: 1400
Регистрация: 14.6.2007
Где: НН(Сормово)

Репутация: 1
Всего: 69



Код

class Controller
{
    protected $_var = array();
    
    // содержит код сохранения переменной $_var
    // например в БД
    public function save(){}
    

    public function action()
    {
        $var['test'] = 'blabla';
    }
    
    public function __set($key, $val)
    {
        //не понял что эта проверка должна делать?
        //if ($key == 'var')
        //вместо вашей напрашивается такая но и она здесь не нужна
        //так как тогда нужно задать все возможные ключи
        //либо работать с приватными атрибутами
        //у вас нет ни того не другого
        //поэтому проверку тоже заключаем в коментарий
        //if(isset($_var[$key]))
        //{
            $_var[$key] = $val;
            //он здесь не нужен если у вам нужно событие на изменение атрибута объекта
            //$this->save();
            //обработчик события, выступает инициатором события
            $this->event($key, $val);
        //}
    }

    private function event($key, $val) {
        echo 'Произошло изменение атрибута ' . $key . ' новое значение ' . $val;
    }
}


Это самый простой пример. В идеале надо реализовать через паттерн наблюдатель, а то мало ли вдруг несколько приемников будет у события.

Это сообщение отредактировал(а) krundetz - 3.6.2013, 09:35


--------------------
!цензоры - Хранитель стратегической жидкости
Группа ТГВ
Группа Нижний Новгород
user posted image
PM MAIL   Вверх
Чучмек
Дата 3.6.2013, 12:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


НЭТ БИЛЭТ
**


Профиль
Группа: Участник
Сообщений: 841
Регистрация: 11.5.2008
Где: СССР

Репутация: нет
Всего: 41



Код

class MyClass
  {
   protected
     $_vars = array();
   public
     function __set($key, $val)
       {
       $this->_vars[$key] = $val;
       }
     function &__get($key)
       {
      // if (!isset($this->_vars[$key]))$this->_vars[$key]=null;
       return $this->_vars[$key];
       }
   }

$obj = new MyClass;
$obj->a[]=666;
$obj->a[]=555;

print_r($obj->a);






--------------------
умную мысль держи при себе, а дурной - поделись с другими 
PM MAIL   Вверх
ShamanVoodoo
Дата 3.6.2013, 17:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 17.10.2007
Где: Сергиев Посад

Репутация: -1
Всего: -3



krundetz> я писал уже может быть не только $_var, но и $_var2 и т.д.
Чучмек> тоже не то т.к. определенный индекс массива нельзя задать
PM MAIL ICQ   Вверх
Чучмек
Дата 3.6.2013, 17:59 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


НЭТ БИЛЭТ
**


Профиль
Группа: Участник
Сообщений: 841
Регистрация: 11.5.2008
Где: СССР

Репутация: нет
Всего: 41



То, не то. Гадание на кофейной гуще. 
Насколько понятен вопрос - настолько точен ответ.
Что ты хочешь контролировать?
Добавление свойств в объект?
Контролировать конкретное свойство(а)?
Контролировать вставляемые ключ=>значение в свойство-массив?



--------------------
умную мысль держи при себе, а дурной - поделись с другими 
PM MAIL   Вверх
Arantir
Дата 3.6.2013, 18:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Рыбак без удочки
**


Профиль
Группа: Участник
Сообщений: 960
Регистрация: 18.11.2012

Репутация: 2
Всего: 55



Кажись наконец-то доперло...
ТС хочет отлавливать вот такое:
Код

$c = new Controller;
$c->var1 = array(); // вызывается Controller::__set
$c->var1['a'] = 0;  // ни одним из приведенных примеров не отлавливается


Это сообщение отредактировал(а) Arantir - 3.6.2013, 18:55


--------------------
interface Жопа {
    // ATTENTION: has to be implemented by every class of the project for proper project work
}
PM   Вверх
Arantir
Дата 3.6.2013, 19:24 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Рыбак без удочки
**


Профиль
Группа: Участник
Сообщений: 960
Регистрация: 18.11.2012

Репутация: 2
Всего: 55



Проблема в том, что изменения массива надо отслеживать в классе объекта массива, а не в классе, где этот объект является простым полем.
придется свой массив создавать:
Код

class InnerArray implements \ArrayAccess 
{
    private $container;

    public function __construct() {
        $this->container = array();
    }

    public function onChange($args = null)
    {
        echo 'changed!';
        // ...
    }

    public function offsetSet($offset, $value) {
        if (is_null($offset)) {
            $this->container[] = $value;
        } else {
            $this->container[$offset] = $value;
        }
        $this->onChange(array('key'=>$offset, 'value'=>$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;
    }
}
Код


class Controller
{
    public $var1 = new InnerArray();



Это сообщение отредактировал(а) Arantir - 3.6.2013, 19:28


--------------------
interface Жопа {
    // ATTENTION: has to be implemented by every class of the project for proper project work
}
PM   Вверх
ShamanVoodoo
Дата 3.6.2013, 22:28 (ссылка)    | (голосов:4) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 17.10.2007
Где: Сергиев Посад

Репутация: -1
Всего: -3



вопрос задан нормально, ArrayObject  вам не известен судя по постам хоть я его и упоминал. вопрос адресован прежде всего профессионалам, был бы он настолько прост я бы его вообще не задал.

Это сообщение отредактировал(а) ShamanVoodoo - 3.6.2013, 22:30
PM MAIL ICQ   Вверх
Fortop
Дата 4.6.2013, 01:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2200
Регистрация: 13.11.2007
Где: Донецк

Репутация: 1
Всего: 42



Цитата(ShamanVoodoo @  3.6.2013,  22:28 Найти цитируемый пост)
вопрос адресован прежде всего профессионалам

Нас звали?
Мы пришли.

Постарайтесь задать вопрос, а не выдавать поток бессвязного бреда как в первом сообщении, тогда получите ответ.

Hint: чтобы свойство реагировало как массив оно должно реализовывать интерфейс массива, что вам и показали в предыдущем примере.
А уж как вы будете реализовывать - это ваши половые трудности.


--------------------
Мир это Я.
Живее всех живых.
PM MAIL   Вверх
awdev
Дата 4.6.2013, 01:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 22.11.2009

Репутация: нет
Всего: 1



Вот такой ###код получился.. разгребай  smile 
Код

<?
class myArray implements ArrayAccess{
    protected $container;
    protected $ob;
    public function __construct($observe) {
        $this->container=array();
        $this->ob = &$observe;
    }
    public function offsetSet($offset, $value) {
        $this->ob->save($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;
        }
    
        
}
class Controller
{
    protected $_vars = NULL;
    public function __construct(){ $this->_vars=new myArray( $this );}

    protected function save($args){
        echo "Saving...{$args[0]}={$args[1]}".PHP_EOL;
    }
    public function __call($name, $args){
        echo "CALL: $name".PHP_EOL;
        $this->$name($args);
    }
    public function __get($key){    
        echo "Get $key".PHP_EOL;
    return $this->_vars;
        
    }
    public function __set($key, $value){
        echo "Set $key=$value".PHP_EOL;
        $this->_vars[$key] = $value;
        $this->save();
    }
}
class Child extends Controller{    
    protected function foo($args){    
        var_dump($args);
    }
}
$c = new Child;
$c->var1['var1']='value11';
$c->var2['var2']='value22';
echo PHP_EOL;
echo "var1 is: ".$c->var1['var1'].PHP_EOL;
echo "var2 is: ".$c->var2['var2'].PHP_EOL;

$c->foo("test");

Вывод:
Цитата


Get var1
CALL: save
Saving...var1=value11
Get var2
CALL: save
Saving...var2=value22

Get var1
var1 is: value11
Get var2
var2 is: value22
CALL: foo
array(1) {
  [0]=>
  string(4) "test"
}


То есть можно использовать много псевдо переменных: $c->foo[1]=1; $c->bar[2]=2;  при этом вызывается метод SAVE при новом значении, ну и функции так же через жопу но можно проследить. вызывается __call
PM MAIL   Вверх
Arantir
Дата 4.6.2013, 02:16 (ссылка) |    (голосов:3) Загрузка ... Загрузка ... Быстрая цитата Цитата


Рыбак без удочки
**


Профиль
Группа: Участник
Сообщений: 960
Регистрация: 18.11.2012

Репутация: 2
Всего: 55



Цитата(ShamanVoodoo @  3.6.2013,  21:28 Найти цитируемый пост)
вопрос адресован прежде всего профессионалам
Черт, даже зарабатывать этим на жизнь уже недостаточно, чтобы это можно было назвать своей профессией  smile 

Цитата(ShamanVoodoo @  3.6.2013,  21:28 Найти цитируемый пост)
ArrayObject  вам не известен судя по постам хоть я его и упоминал
Если Вы знаете решение, то в чем проблема?

ArrayObject как раз таки ArrayAccess и реализует, на который в первую очередь PHP и опирается при определении корректности использования квадратных скобочек на объект. Остальное в нем — это свистели и переделки массива как такового, вроде сортировки. Если они Вам нужны — пожалуйста, реализовывайте, никто же не запрещает.
Вы дали понять только то, что хотите отловить момент изменения элемента массива. Для этого достаточно ArrayAccess.


Создавать свой класс для массива придется в любом случае, иначе впихнуть ивент будет просто некуда.
Если Вам хочется вынести ивент в класс Controller, то это делается несложно:

Код

class Controller implements Listener
{
    public $var;
    
    public function __construct()
    {
        $this->var = new InnerArray($this);
    }

    public function event($args)
    {
        echo "{$args['key']} saved as {$args['value']}";
    }
}
Код

interface Listener
{
    public function event($args);
}

class InnerArray implements \ArrayAccess 
{
    private $container = array();
    private $listener;

    public function __construct(Listener $listener) {
        $this->listener = $listener;
    }

    public function offsetSet($offset, $value) {
        if (is_null($offset)) $this->container[] = $value;
        else $this->container[$offset] = $value;
        $this->listener->event(array('key'=>$offset, 'value'=>$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;
    }
}


Код

$c = new Controller;
$c->var['foo'] = 'bar';
Код

foo saved as bar 



--------------------
interface Жопа {
    // ATTENTION: has to be implemented by every class of the project for proper project work
}
PM   Вверх
Страницы: (3) Все [1] 2 3 
Ответ в темуСоздание новой темы Создание опроса

Внимание: данный раздел предназначен для решения сложных, нестандартных задач.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Для профи | Следующая тема »


 




[ Время генерации скрипта: 0.0895 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.