Решение: История просмотров на MODx Revo

Реализация сниппета, который бы выводил историю просмотренных страниц.

Ранее создавал «Вопрос» История просмотренных страниц на MODx Revo, в ней Василий Наумкин поделился ссылкой, на содержании данной ссылки, спустя время, написал сниппет.

Представляю к вашему вниманию.

Сниппет LastView:
<?php
$id = $modx->resource->id;

if (!isset($limit)) {$limit = 10;}
if (!isset($show)) {$show = 0;}
if (!isset($snippet)) {$snippet = 0;}
if (!isset($parents)) {$parents = 0;}
if (!isset($tpl)) {$tpl = 'tpl.LastView';}
if (!isset($except)) {$except = 0;} else {$except = split(",",$except);}

// Проверяем исключения
if($except != false) {
    $add = 1;
    foreach ($except as $value) {
        if($value == $id) {$add = 0;}
    }
}

// Добавляем просмотренную страницу
if ($add != false) {
    if (!isset($_SESSION['viewed'])) {
    	$_SESSION['viewed'] = array($id);
	} else {
		if (in_array($id, $_SESSION['viewed'])) {
			$key = array_search($id, $_SESSION['viewed']);
			unset($_SESSION['viewed'][$key]);
		}

		if (count($_SESSION['viewed']) > $limit) {
			array_shift($_SESSION['viewed']);
		}
		
		$_SESSION['viewed'][] = $id;
	}
}

// Предварительные проверки
if ($show == '1') {
    if (!isset($_SESSION['viewed'])) {return;}
	$ids = array_reverse($_SESSION['viewed']);
    if (empty($ids)) {return;}
}

// Выводим просмотренные страницы без вызова сниппета
if ($show == '1' && $snippet == false) {
    $output = '';
    foreach ($ids as $tsID) {
        if($tsID != $id) {
            $page = $modx->getObject('modResource', $tsID)->toArray();
            $output .= $modx->getChunk($tpl, $page);
        }
    }
    return $output;
}

// Выводим просмотренные страницы через вызов сниппета
if ($show == '1'  && $snippet != false) {
	$config = array(
		 'resources' => '-'.$id.','.implode(',', $ids)
		,'parents' => $parents
		,'limit' => $limit
		,'tpl' => $tpl
	);
	return $modx->runSnippet($snippet, $config);
}

пример вызова:
[[!LastView? &limit=`10` &show=`1` &snippet=`0` &parents=`0` &tpl=`tpl.LastView` &except=`[[++site_start]],404,502`]]

пример шаблона tpl.LastView:
<a href="[[~[[+id]]]]">[[+pagetitle]]</a>
так же можно использовать вывод любых других данных документа

доступные значения:
  • &limit — лимит отображаемых и записываемых id страниц, по умолчанию 10
  • &show — отображать страницы или нет (0/1), по умолчанию 0 (будет записывать, но не отображать)
  • &snippet — наименование сниппета, с помощью которого будут выводиться данные (pdoResources, getResources и т.п.), по умолчанию 0 (false, то будет выводить данные с помощью modResource)
  • &parents — id родительского документа, по умолчанию 0
  • &tpl — наименования чанка с шаблоном, по умолчанию tpl.LastView.
  • &except — id исключаемых документов через запятую, по умолчанию 0.


Мой пример: Проект про офтальмологию (История просмотров, перед футером страницы)
.

— Вот и всё, возможно кому нибудь пригодится

Следующая заметка
Переключение контекстов в зависимости от URL
Предыдущая заметка
Вывод секций для публикаций Tickets


Комментарии ()

  1. Александр Котлов 07 октября 2013, 18:15 # 0
    Большое спасибо!
    1. Павел Левин 07 октября 2013, 18:40 # 0
      Всегда пожалуйста
    2. Александр Наумов 07 октября 2013, 19:01 # 0
      Спасибо за сниппет!!!
      1. Александр Котлов 07 октября 2013, 19:04 # +1
        А если еще в начало вставвить

        if (!isset($thumbs)) {$thumbs = '120x90';}</b>
        
        а в конец

        ,'tpl' => $tpl
         ,'includeThumbs' => $thumbs,
        
        то он будет отлично выводить картинку просмотренного товара минишоп)
        1. Антон Соловьёв 08 октября 2013, 11:21 # 0
          прощения за офтоп, но зачем на сайте куркод, что даёт? я не собираюсь холифарить, просто короткий ответ.
          1. Павел Левин 08 октября 2013, 12:14 # 0
            В смартфонах есть функция распознания qr-кода, соответственно можно спокойно сфоткать монитор или распечатку с qr-кодом и перейти на страницу, в данном примере, каждая страница имеет свой qr-код, в котором url текущей страницы. Пока мобильной версии нет, но планируется.

            Пользователи разные бывают :-)
            1. Антон Соловьёв 08 октября 2013, 12:21 # 0
              Но если они уже в интернете на стационарном компе, зачем и с мобилы входить? продолжить чтение в транспорте типа?
              1. Воеводский Михаил 08 октября 2013, 12:29 # 0
                Можно в транспорте, а можно на мобильнике оставить открытым окно с контактами, когда собираешься ехать в эту компанию. Ситуации бывают разные :)
                1. Антон Соловьёв 08 октября 2013, 12:38 # 0
                  Спасибо. Наконец-то дошло )
          2. Павел Левин 08 октября 2013, 14:41 # 0
            Поправил код, добавив исключение текущей страницы из вывода.
            1. Mihan 13 ноября 2013, 21:25 # 0
              Отличное решение, спасибо.

              Вывожу перед сниппетом текст «Вы недавно смотрели:». Не подскажете, как скрывать его, если массив пустой?
              1. Павел Левин 14 ноября 2013, 14:53 # 0
                Можно дописать скрипт:
                // Предварительные проверки
                if ($show == '1') {
                    if (!isset($_SESSION['viewed'])) {return;}
                	$ids = array_reverse($_SESSION['viewed']);
                    if (empty($ids)) {return;}
                	echo '<h3>Вы недавно смотрели:</h3>';//заголовок
                }
              2. Александр Москвин 14 ноября 2013, 12:22 # 0
                Что-то сайт подтормаживает.
                3.9 секунды одну страницу открывает, потом 0.69.

                Когда я делал сайт tokyorope.ru/ — я максимально увеличил скорость генерации, сам можешь заценить.
                1. Павел Левин 14 ноября 2013, 14:50 # 0
                  На сайте громоздкое меню, плюс проверка нового, в отличии от меню, проверка нового не кэшируется.
                  В остальном пока думаю, что делать, много фильтров использовано.
                2. Вадим Еременко 21 апреля 2014, 11:02 # 0
                  Добрый день! Сниппет работает отлично, но один момент никак не пойму — как подключить вывод ТВ параметров? В частности нужно изображение и цена… Просьба сильно ногами не пинать — первый проект на Revo) Спасибо)
                  1. Aleksey 04 июля 2014, 13:49 # 0
                    Добрый день, у вас получилось сделать вывод ТВ?
                  2. Aleksey 04 июля 2014, 13:48 # 0
                    Всем доброго дня, а как сделать чтобы тв параметры из шаблона тоже парсились? Заранее спасибо за ответ
                    1. Павел Левин 04 июля 2014, 14:02 # 0
                      Мне кажется вам сюда. Думаю речь идет о товарах?
                      1. Aleksey 04 июля 2014, 14:14 # 0
                        Да речь о товарах. По ссылке, что вы прислали про тв ничего нет.
                        1. Павел Левин 04 июля 2014, 15:07 # 0
                          Там есть упоминания в коде.
                          Template Variables
                          Getting the processed value of a TV from the current document (or any document you have a reference to) is easy with this method (note that both instances of the letter 'V' in getTVValue() are capitalized):

                          $val = $modx->resource->getTVValue('name_of_tv');
                          $val = $modx->resource->getTVValue($id); // ID of the TV (not the document)
                          or
                          $resource = $modx->getObject('modResource',array('pagetitle'=>'SomePage'));
                          $val = $resource->getTVValue('name_of_tv');
                          $val = $resource->getTVValue($id); // ID of the TV (not the document)

                          Getting the value of a TV in another document is a little more tricky because the processed value of the TV can be different for each document it's embedded in. As a result, you have to either get the resource object using the method above, or use specific methods of the TV and send along the ID of the document. Assuming that $id is the ID of the document (not the TV):

                          /* Get the TV */
                          $tv = $modx->getObject('modTemplateVar',array('name'=>'MyTV'));
                          
                          /* get the raw content of the TV */
                          $rawValue = $tv->getValue($id);
                          
                          /* get the processed content of the TV */
                          $processedValue = $tv->renderOutput($id);
                          1. Aleksey 04 июля 2014, 15:20 # 0
                            спасибо огромное
                          2. Павел Левин 04 июля 2014, 15:20 # 0
                            По идее.
                            Просто надо дописать необходимые параметры в массив согласно документации сниппета и вызывать через pdoResources или getResources, самый простой вариант:

                            // Выводим просмотренные страницы через вызов сниппета
                            if ($show == '1'  && $snippet != false) {
                            	$config = array(
                            		 'resources' => '-'.$id.','.implode(',', $ids)
                            		,'parents' => $parents
                            		,'limit' => $limit
                            		,'tpl' => $tpl
                            		,'includeTVs' => '1'
                            		,'includeTVList'='image,price'//необходимые поля для вывода
                            	);
                            	return $modx->runSnippet($snippet, $config);
                            }
                      2. Саша Иващенко 21 июля 2014, 03:52 # 0
                        а как не показывать каталоги? а оставить только документы
                        1. Павел Левин 21 июля 2014, 09:41 # 0
                          Думаю если поставить после

                          ,'tpl' => $tp
                          эту строку

                          ,'isfolder' => ''
                          То каталоги, которые имеют значение «1» не будут выводиться.
                          Не знаю точно, возможно там и «0» в место пустоты, надо пробовать.
                          Можно поиграть с 'true' и 'false'
                          1. Павел Левин 21 июля 2014, 09:47 # 0
                            Хотя, если получше подумать, стоит прервать добавление в список страниц.

                            За основу возьмем этот код:
                            <?php
                            if ($modx->resource->get('isfolder')) {
                                $output .= "It's marked as a container</p>";
                            }
                             
                            if ($modx->resource->hasChildren()) {
                             
                            $output .= "<p>This document has Children</p>";
                            }
                             
                            return $output;
                            ?>

                            и вставим
                            $modx->resource->get('isfolder')

                            внутрь условия
                            if ($add != false) {

                            получаем
                            if ($add != false && !$modx->resource->get('isfolder')) {

                            В результате, каталоги не пройдут в список истории просмотра.
                            Должно работать =)
                          Добавление новых комментариев отключено.