Косвенная модификация перегруженного свойства - PullRequest
0 голосов
/ 28 декабря 2010

Я создаю форум и хочу отслеживать, какие темы были обновлены с момента последнего посещения пользователя. Итак, у меня есть массив, который я храню в $ _SESSION, который в основном структурирован как [$boardid][$threadid] = 1. Если Threadid и BoardID установлены, то нить не была прочитана, и доска содержит непрочитанные нити. Когда пользователь просматривает поток, я просто unset() вижу соответствующую плату и идентификатор потока. Однако у меня возникли проблемы с отключением для работы с такими массивами.

Во-первых, у меня есть класс сеанса, чтобы сделать обработку данных сеанса немного лучше

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]);
}

};

Тогда у меня есть класс CurrentUser, представляющий текущего пользователя. Класс CurrentUser имеет член с именем _data, который является объектом Session. В классе CurrentUser я переопределяю методы __get и __set для использования члена _data.

    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;
}

Теперь, чтобы отследить, какие темы были непрочитанными, я выбираю все темы, чья дата> = дата last_seen пользователя. У меня также есть методы для удаления доски и потоков из массива.

    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]);
}

Здесь я сталкиваюсь с проблемами. Я получаю ошибку Indirect modification of overloaded property Session::$unreadThreadsList has no effect на $threads =& $this->_data->unreadThreadsList; Как можно решить эту проблему или найти лучшее решение? Я думал о создании класса, который следит за массивом, чтобы у меня не было массива массивов массивов массивов, но я не уверен в сохранении объектов, а создание объекта просто для управления массивом кажется действительно грязным для меня.

1 Ответ

0 голосов
/ 29 декабря 2010

Извините, если я немного сбился с базы; Я пытаюсь понять, как используются переменные (так как их инициализация не показана). Поэтому $ this-> unreadThreadsList - это массив, в котором находятся индексы (если значение установлено в 1). Почему бы не установить все напрямую?

Глядя на то, что вы делаете, у меня есть идея. Он делает то же самое, но просто выполняет дополнительную проверку $ this-> unreadThreadsList и напрямую обращается к переменной.

Если я правильно понял структуру массива, это должно сработать.

 public function buildUnreadList($since) {
    // Build a "new since last visit" list
    $forumModel = new Model_Forum;
    $newThreads = $forumModel->fetchThreadsSinceDate($since);
    foreach($newThread as $thread)
    {
        // Avoid an error if no list pre-exists
        if(is_array($this->unreadThreadsList))
            if(array_key_exists($thread['board'],$this->unreadThreadsList))
                if(array_key_exists($thread['id'],$this->unreadThreadsList[$thread['board']]))
                    // Skip this result, already in
                    if($this->unreadThreadsList[$thread['board']][$thread['id']] == 1) continue;
        $this->unreadThreadsList[$thread['board']][$thread['id']] = 1;
    }
 }

Это предполагает структуру массива, такую ​​как:

array(
    1 => array(
      'board' => 1,
      'id' => 2
    ),
    2 => array(
      'board' => 3,
      'id' => 1
    ),
    3 => array(
      'board' => 7,
      'id' => 2
    ));

для результата "fetchThreadsSinceData ($ since)" и структуры массива

 array(
    1 => array(
      2 => 1
    ),
    2=> array(
      2 => 1
    ),
    3=> array(
      2 => 1
    ));

для $ this-> unreadThreadsList, где первый индекс - это доска, а второй индекс - это идентификатор потока.

Для других функций, почему бы просто не сбросить их напрямую?

unset($this->unreadThreadsList[$boardid][$threadid]);
unset($this->unreadThreadsList[$boardid]);

Удачи!
Деннис М.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...