Notify Property Changed
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

&lt;?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-&gt;callback != null){
            call_user_func($this-&gt;callback, $name);
        }

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

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

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

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

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

class SampleClass extends NotifyPropertyChanged
{
}

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


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

array(1) {
    ["name"]=&gt;   
    array(2) {
        [0]=&gt; 
        string(5) "value"
        [1]=&gt; 
        string(4) "test"
    }
}