Page 1 of 1

Indirect modification of overloaded property

Posted: Tue Dec 28, 2010 5:53 pm
by Cirdan
I'm creating a forum, and I want to keep track of which threads have been updated since the user last visited. So I have an array that I keep in $_SESSION that is basically structured as [$boardid][$threadid] = 1. If the threadid and boardid are set, then the thread has not been read and the board contains unread threads. When a user views a thread, I just unset() the appropriate board and thread id. However, I've having problems with getting unset to work with arrays like this.

Firstly, I have a session class to make handling session data a little nicer

Code: Select all

class Session {
private $_namespace;

public function __construct($namespace = '_default') {
    $this->_namespace = $namespace;
}

/**
 * Erase all variables in the namespace
 */
public function clear() {
    unset($_SESSION[$this->_namespace]);
}

public function __set($name, $value) {
    $_SESSION[$this->_namespace][$name] = $value;
}

public function __get($name) {
    if(isset($_SESSION[$this->_namespace]) && array_key_exists($name, $_SESSION[$this->_namespace])) {
        return $_SESSION[$this->_namespace][$name];
    }

    return null;
}

public function __isset($name) {
    return isset($_SESSION[$this->_namespace][$name]);
}


public function __unset($name) {
    unset($_SESSION[$this->_namespace][$name]);
}

};
Then I have a CurrentUser class representing the current user. The CurrentUser class has a member named _data which is-a Session object. In the CurrentUser class I override the __get and __set methods to use the _data member.

Code: Select all

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

public function __isset($name) {
    return isset($this->_data->$name);
}

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

    return null;
}
Now to keep track of which threads have been unread, I fetch all threads whose date is >= the user's last_seen date. I also have methods to remove board and threads from the array.

Code: Select all

public function buildUnreadList($since) {
    // Build a "new since last visit" list
    $forumModel = new Model_Forum();
    $newThreads = $forumModel->fetchThreadsSinceDate($since);
    foreach($newThreads as $thread) {
        $tmp =& $this->unreadThreadsList;
        $tmp[$thread['board']][$thread['id']] = 1;              
    }
}
public function removeThreadFromUnreadList($boardid, $threadid) {
    $threads =& $this->unreadThreadsList;
    unset($threads[$boardid][$threadid]);   
}

public function removeBoardFromUnreadList($boardid) {
    $threads =& $this->_data->unreadThreadsList;
    unset($threads[$boardid]);
}
This is where I'm running into problems. I'm getting an "Indirect modification of overloaded property Session::$unreadThreadsList has no effect error on $threads =& $this->_data->unreadThreadsList;" error. How can I either fix this problem or design a better solution? I thought about creating a class that keeps track of the array so I don't have to have an array of arrays of arrays of arrays, but I'm not certain on persisting objects though a session and creating an object just to manage an array feels really dirty to me.