$obj->hidden non ti stampa nulla perchè $hidden è una variabile dichiarata privata, quindi quando la richiami dall'esterno dell'oggetto, non è visibile e quindi usa __get e quindi non ti stampa nulla perchè non esiste in $data. Se tu facessi $obj->hidden = 2; echo $obj->hidden, per come è strutturato l'esempio allora vedresti in output 2, ma dall'esterno sono due variabili differenti quella interna private e quella valorizzata con __set. Personalmente, odio usare __get/__set e relativi isset/unset anche perchè non ne vedo l'utilità.