3
\$\begingroup\$

Inspired by a SO post, just as an exercise, I tried to implement a way of notifying a consumer of a class about whether a property on an object has changed or not. I'm not attempting to use this in anyway, but I would like to learn from it.

interface INotifyPropertyChanged
{
    function PropertyChanged($name);
    function RegisterChangeCallback($callback);
}

abstract class NotifyPropertyChanged implements INotifyPropertyChanged
{
    public $changes;
    public $trackChanges;
    private $callback;

    public function PropertyChanged($name)
    {
        if( $this->callback != null){
            call_user_func($this->callback, $name);
        }

        if( !isset($this->changes))
            $this->changes = Array();

        if( !in_array($name, $this->changes))
            $this->changes[] = $name;
    }

    public function RegisterChangeCallback($callback) 
    { 
        $this->callback = $callback;
    }

    public function __set($name, $value) 
    { 
        $previousValue = $this->$name;
        $this->$name = $value;      

        if( $this->trackChanges && $previousValue !== $value) {         
            $this->PropertyChanged($name);
        }
    }

    public function __get($name) 
    { 
        return $this->$name;
    }
}

Then, implementing a class;

class SampleClass extends NotifyPropertyChanged
{
    protected $name;
}

And finally, usage;

$class = new SampleClass();
$class->name = "value";
$class->trackChanges = true;
$class->name = "test";
var_dump($class->changes);

And if you want, you can call $class->RegisterChangeCallback(..) to be told when it does change.

Like I said, I'm not planning on using this, it was an exercise to see if I could do something similar to .NETs INotifyPropertyChanged. And, what better way to get feedback on an idea.

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

First of all it is useless to use __set or __get if you're trying to access the non existing property that might also cause a cyclic request of the method. Instead you should have an array that contains the values now second thing if you will have the property inside the object the __set or __get methods won't be called. So you should fix those and it should work. If needed I will post a code with the fix

<?php
interface INotifyPropertyChanged
{
    function PropertyChanged($name);
    function RegisterChangeCallback($callback);
}

abstract class NotifyPropertyChanged implements INotifyPropertyChanged
{
    public $changes;
    public $trackChanges;
    private $callback;
    protected $values = array();
    public function PropertyChanged($name)
    {
        if( $this->callback != null){
            call_user_func($this->callback, $name);
        }

        if( !isset($this->changes))
            $this->changes = Array();

        if( !in_array($name, $this->changes))
            $this->changes[$name][] = $this->$name;
    }

    public function RegisterChangeCallback($callback) 
    { 
        $this->callback = $callback;
    }

    public function __set($name, $value) 
    { 
        $previousValue = $this->$name;
        if( $this->trackChanges && $previousValue !== $value) {         
            $this->PropertyChanged($name);
        }
        $this->values[$name] = $value;      
    }

    public function __get($name) 
    { 
    if(array_key_exists($name,$this->values)){
        return $this->values[$name];
        }
        return null;
    }
}

class SampleClass extends NotifyPropertyChanged
{
}

$class = new SampleClass();
$class->name = "value";
$class->trackChanges = true;
$class->name = "test";
$class->name = "test2";
var_dump($class->changes);

the above code results which also allows you to have all changes

array(1) {
    ["name"]=>   
    array(2) {
        [0]=> 
        string(5) "value"
        [1]=> 
        string(4) "test"
    }
}
\$\endgroup\$
2
  • \$\begingroup\$ I did see that changing the property from within the class does not trigger the changes, which would be pretty useless if you were using your class for anything but a DTO. If you have a better version, I would appreciate you sharing. Like I said, I posted this to learn from. \$\endgroup\$ Commented Aug 14, 2014 at 17:32
  • \$\begingroup\$ i've updated the answer \$\endgroup\$
    – Eli Y
    Commented Aug 14, 2014 at 17:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.