[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
2 784
+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