[ViewsOnline] Статистика кто онлайн для страницы

Задался таким вопросом в связи с необходимостью вывести следующую надпись для форума:
Читают тему гостей 15, пользователей 2 (user1, user5)

В итоге родился небольшой сниппет на базе таблицы просмотров от Tickets.

Для работы скрипту нужны:
  1. установленный pdoTools
  2. включённый Fenom в настройках pdoTools
  3. установленный Tickets
  4. разрешён в настройках Tickets подсчёт просмотров гостями
Эти дополнения бесплатны и на их базе работает сниппет view_online:


<?php
// подключаем pdoTools для работы INLINE чанков 
if (file_exists(MODX_CORE_PATH . 'components/pdotools')) {$pdoTools = $modx->getService('pdoTools');}

// все возможные параметры для сниппета
if (!empty($tpl)) {$tpl = $scriptProperties['tpl'];} else {$tpl = '@INLINE Читают тему {$guests|declension:\'гость|гостя|гостей\':true}, {$users|declension:\'пользователь|пользователя|пользователей\':true}{if $users} ({$userlist}){/if}';}
if (!empty($tpl_userlist)) {$tpl_userlist = $scriptProperties['tpl_userlist'];} else {$tpl_userlist = '@INLINE {$separator}{$user|user:\'fullname\'}';}
if (!empty($pid)) {$pid = $scriptProperties['pid'];} else {$pid = $modx->resource->id;}
if (!empty($separator)) {$separator = $scriptProperties['separator'];} else {$separator = ', ';}
if (!empty($min)) {$min = $scriptProperties['min'];} else {$min = 15;}
$min = date('Y-m-d H:i:s', strtotime("-15 min") );

$output = "";

// Выборка просмотров за последние 15 минут
$q = $modx->prepare("SELECT * FROM modx_tickets_views WHERE parent = '{$pid}' AND timestamp > '{$min}' ORDER BY timestamp DESC");
$q->execute();
$r = $q->fetchAll(PDO::FETCH_ASSOC);

$users = $arr = array();
$arr['total'] = count($r);
$arr['guests'] = $arr['users'] = $i = 0;
$arr['userlist'] = '';

foreach($r as $row){
    $i++;
    if($row['uid'] > 0) {
        if($id > 1) {$userslist['separator'] = $separator;}
        $userslist[] = $row['uid'];
        $arr['userlist'] .= $pdoTools->getChunk($tpl_userlist, $userslist); // список пользователей
        $arr['users']++;
    } else {
        $arr['guests']++;
    }
}

return $pdoTools->getChunk($tpl, $arr);

Параметры сниппета

  • tpl — чанк для вывода информации, активно используются возможности Fenom. Плейсхолдеры чанка: total, guests, users и userlist. По умолчанию:
    @INLINE Читают тему {$guests|declension:\'гость|гостя|гостей\':true}, {$users|declension:\'пользователь|пользователя|пользователей\':true}{if $users} ({$userlist}){/if}
  • tpl_userlist — чанк для вывода списка пользователей, принимает 2 плейсхолдера: separator и user. По умолчанию:
    @INLINE {$separator}{$user|user:\'fullname\'}
  • separator — разделитель для списка пользователей. По умолчанию: ', '
  • pidот page id, id страницы для вывода статистики. По умолчанию текущая
  • minот minutes, количество минут, в течении которых пользователь считается на сайте. По умолчанию: 15

Теперь вызываем сниппет некэшируемым на нужной нам странице:
{'!view_online'|snippet}

Пример вызова статистики для какой-то другой страницы:
{'!view_online'|snippet: [
    'pid' => 1,
]}

Вот и всё! Всю работу за нас делают pdoTols и Tickets (за что не забываем денно и ношно благодарить Василия), а наш сниппет-надстройка просто выводит и правильно структурирует нужную нам информацию. Поэтому и не думаю что есть смысл его оформлять отдельным пакетом для репозитория.

***

UPD. Переписал весь код и собрал всё это дело в пакет. Теперь сниппет называется ViewsOnline! Появились чанки, новые параметры, исправлены ошибки. (подробнее смотри в changlog)

Василий Столейков
08 сентября 2016, 17:24
modx.pro
9
3 127
+10
Поблагодарить автора Отправить деньги

Комментарии: 22

Евгений
08 сентября 2016, 20:40
0
Только с тикетсом работает? Или можно и к любой странице прикрутить, если вообще не установлен тикетс?
    Василий Столейков
    08 сентября 2016, 20:43
    +1
    Работает с любой страницей, но тикетс должен быть установлен. То есть тикетс подсчитывает статистику для всех страниц сайта.
    Роман Садоян
    08 сентября 2016, 21:53
    +1
    Поэтому и не думаю что есть смысл его оформлять отдельным пакетом для репозитория.
    Не помешало бы.
    $q = $modx->prepare("SELECT * FROM modx_tickets_views WHERE parent = '{$pid}' AND timestamp > '{$min}' ORDER BY timestamp DESC");
    Нужно заметочку, что бы не забыли изменить префикс у кого он не modx

    А в целом, Василий, благодарю хорошая работа, дал в репу!
      Василий Столейков
      08 сентября 2016, 22:12
      0
      Ок, спасибо, попробую. Это будет мой первый опыт оформления в репозиторий. Спасибо за заметку про префикс.
        Иван Климчук
        09 сентября 2016, 09:57
        0
        Нужно таки намутить отдельный репозиторий для сниппетов :) А то если честно, код сборки пакета будет больше, чем сам сниппет.
          Сергей Шлоков
          09 сентября 2016, 10:07
          0
          Этот репозиторий есть — готовые решения. ;) Плохо тегов тут нет.
            Иван Климчук
            09 сентября 2016, 10:21
            +1
            С этим согласен, но тут они обычно в виде заметок, не всегда удобно выдирать код из заметки или искать линки.
              Василий Столейков
              09 сентября 2016, 10:37
              0
              Поэтому и оформил в пакет и выложил ссылку. Действий гораздо меньше — установил и не паришь себе мозги с копипастами всякими… ))
                Сергей Шлоков
                09 сентября 2016, 10:42
                0
                Как раз наоборот. Посчитай количество шагов в том и другом случае. Лично я не стал бы ставить пакет ради одного сниппета. Тем более обновлений не планируется.
              Василий Столейков
              09 сентября 2016, 10:33
              0
              Выложил ссылку на пакет сюда, в репозиторий «готовые решения» ;)
                Василий Столейков
                09 сентября 2016, 10:40
                0
                Т.к. это уже не просто сниппет, а и пакет, перенёс топик в «Новые дополнения и их версии».
                Василий Столейков
                09 сентября 2016, 10:07
                0
                )))
              Сергей Шлоков
              09 сентября 2016, 08:18
              1
              +1
              Хорошее решение. Только лучше таблицу напрямую не указывать. MODX сам умеет определять
              SELECT * FROM {$modx->getTableName('TicketView')} WHERE ....
                Иван Климчук
                09 сентября 2016, 09:58
                +1
                Плюсую, как выше заметили, это так же решает проблему отличного от modx префикса.
                  Василий Столейков
                  09 сентября 2016, 10:32
                  0
                  Да, спасибо, я уже решил эту проблему и переписал весь сниппет под пакет…
                  Там много изменений в параметрах, их названиях и в названии самого сниппета. Посмотрим как отреагирует магазин и примет ли его…
                Василий Столейков
                09 сентября 2016, 10:33
                0
                Обновил статью, выложил транспортный пакет и демо для просмотра работы
                  Алексей Андреев
                  26 января 2017, 13:49
                  0
                  Почему-то на части страниц выводит примерно как нужно, а на части вылезает просто код.
                  Нормально показывает там, где есть вызов getTickets и почему-то еще AjaxForm (FormIt). При этом на всех страницах есть вызов TicketLatest.



                  И при parents=0 всё равно считает посетителей для каждой страницы, а я хотел показать сколько всего в данный момент на сайте гостей и юзеров.
                    Василий Столейков
                    26 января 2017, 13:55
                    1
                    0
                    А в логи что-то пишется?
                      Алексей Андреев
                      26 января 2017, 13:58
                      0
                      [2017-01-26 11:02:37] (ERROR @ /web/core/components/pdotools/model/pdotools/pdotools.class.php : 940) Unexpected tag 'display' in 4e4426b62082931c8782625cb4787966 line 114, near '{display:' <- there
                      Не знаю, относится это к делу или нет, но похоже. pdoTools свежий.
                  Василий Столейков
                  26 января 2017, 14:05
                  1
                  +1
                  Нет, это похоже на конфликт фенома с javascript на странице. Найди в коде страницы {display: и добавь пробел после фигурной скобки вот так { display:.
                  Этот конфликт и мешает запуску сниппета на тех неработающих страницах. Именно там и ищи.
                    Алексей Андреев
                    26 января 2017, 14:23
                    0
                    И правда, сработало =) спасибо
                    А что делать с parents=0?
                    Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
                    22