Переползаем с Ditto на Doclister

Итак, после знакомства с Доклистером я прикипел к нему всеми фибрами. Это очень хорошая штука. И если вы еще раздумываете использовать его или нет, то даже не думайте, юзайте на здоровье! Вы еще скажете спасибо, если сталкивались с фильтрацией в дитто, где она сделана через жопу :)
Итак пробегусь по самым основным моментам которые чаще всего встречаются мне. Разберем простой пример (такое написание сниппета работает только если у вас отключен TinyMCE (иначе при переносе строк вставятся BR и ничего не заработает):


[[DocLister? 
&idType=`documents`
&documents=`1,2,3` 
&tpl=`имя чанка`
&tvList=`tvname1,tvname2`
&tvPrefix=``
&orderBy=`menuindex DESC`
&id=`list`
&filters=`tv:price:gt:100`
&depth=`3`
]]


итак &idType — параметр показывающий как мы будем выводить документы, либо списком из конкретно указанных id (idType=`documents`) либо берем родительский документ и показываем все что находится в нем в соответствии с другими параметрами. Это вроде просто :) тогда у нас будет (idType=`parents`) в дитто этих параметров нет.
Тогда если если мы указываем idType=`documents` значит следующий параметр у нас будет documents=`1,2,3` (как в примере) Если же &idType=`parents` то следующий параметр должен быть parents=`1,2,3` со списком родителей.

&tpl — здесь все как в дитто, но возможности гораздо шире. Но сейчас я углубляться не буду. Для новичков достаточно простого примера.

&tvList — в дитто этого нет. Это список всех задействованных TV которые будут использоваться у вас в чанке &tpl. Перечислить надо правильно все через запятую. Следующий параметр тоже обязательный
&tvPrefix=`` — что это значит и почему он должен быть пустым? Пустым он должен быть для того чтобы в чанке наши TV-плейсхолдеры выглядели привычно, как в дитто [+tvname1+], в случае если &tvPrefix=`tv` наш плейсхолдер будет таким [+tv.tvname1+]

&orderBy — аналогично дитто. Если нужен случайный вывод, делаем так &orderBy=`RAND()` Интересный момент для сортировке в случае если нам надо вывести несколько конкретных документов по их айди в указанном в списке порядке &documents=`1,3,2` то значит указываем &sortType=`doclist`

&id — аналогично Ditto. Если используете несколько DL на странице, делайте разные ID. Иначе проблемы неизбежны. Также id юзается для пагинации.

&filters=`tv:price:gt:100` — это фильтрация по TV. И только по ТВ. По полям документа будет возможно в следующей серии :)
Итак здесь все просто — выводим документ у которого tv price больше 100.
Аналогичная запись tv:price:>:100 Но у меня иногда > и gt работали по разному. Не знаю почему, но юзайте то что правильнее работает именно у вас :)
Часто нужно указывать несколько критериев. Не проблема. &filters=`AND(tv:price:gt:100;tv:ves:lt:5)`

&depth — аналогично дитто.

Если топик понравился уважаемому сообществу, то я готов сделать урок 2 где расскажу про фильтрацию по документам modx и пагинацию и phx.

скачать последнюю версию всегда можно здесь github.com/AgelxNash/DocLister

описание параметров для пытливых умов blog.agel-nash.ru/addon/doclister.html

P.S. Данный урок был профинансирован госдепом США :D

71 комментарий

avatar
1) Я бы добавил, что OrderBy работает не так как в Ditto, а так, как в MySQL
2) idType на мой взгляд одна из важнейших вещей (странно, что этого небыло раньше). Т.к. благодаря этому параметру можно жестко определить от куда берутся параметры если вдруг &parents или &documents пуст. А что бы мы должны были делать, если бы эти два параметра были одним целым?
3) filters — хоть и не идеальная штука, но фильтровать она умеет. Я бы посоветовал фильтровать через AddWhereList по основным параметрам документа (если используется контроллер site_content) и только для ТВ использовать filters.

P.S. хотелось бы увидеть больше реальных примеров по переходу с Ditto на DocLister. Для начала хотя бы просто вызовы…
avatar
Если топик понравился уважаемому сообществу, то я готов сделать урок 2 где расскажу про фильтрацию по документам modx и пагинацию и phx.
Лучше рассказать, как обойтись без phx (а также без if и любых других сниппетов в tpl) c помощью &prepare.
avatar
phx подключается только тогда, когда это реально нужно. If бред, т.е. его синтаксис очень похож на php. А коли так, то зачем эту разницу? Но согласен. Пример нужен.
avatar
Чтобы проверить, прикреплена ли к записи картинка в списке — писать сниппет? Не смешите
avatar
когда вопрос стоит по части скорости работы :) то очень даже не смешно :)
ибо банально php тратит на разбор параметров снипета в 5-10 раз больше времени чем собственно на операции в этом снипете :)

а теперь представьте что у вас таких снипетов 100 вот так по миллисекунде и собирается все.

особенно это заметно когда вывод на страничке 50 товаров и в шаблоне дитто еще штук 10-15 мелких проверок. итого уже разбор 500-750 параметров сниппетов :)
avatar
Мой случай с новостной лентой такой же частный как ваш список товаров — в списке товаров я бы вообще обошелся TV типа картинка с обязательным значением по умолчанию в виде пустой картинки с надписью «изображение отсутствует», т.к. крайне часто элемент списка товаров представляет из себя кубик, в которое это самое изображение вписано, то есть без него не дизайнится. А в случае же вывода ленты новостей из 5-10 штучек на страницу проседание КПД не видно. Так что и тут и там — это две большие разницы, и разумеется, разный подход
avatar
У нас тут как бы Creative freedom: можно писать сниппет, можно не писать, можно писать в «Вопросы» и ждать, пока кто-нибудь другой напишет. Я же просто прошу автора обратить внимание на опцию «писать сниппет» в виде &prepare, а там уже читатели сами пусть решают.
По варианту «не писать сниппет» есть, к примеру, решение некой задачи из топика про if:
[[if? &is=`[*marka*]:is:Audi` &then=`{{features-audi}}` ]]
[[if? &is=`[*marka*]:is:BMW` &then=`{{features-bmw}}` ]]
[[if? &is=`[*marka*]:is:LADA` &then=`{{features-lada}}` ]]

И задачу решили, и сниппет писать не стали, все серьезно в общем. А там может кто-нибудь напишет сниппет Switch и сниппет Var и совсем хорошо будет — как в том топике на stackoverflow про сложить два числа, используя jQuery.
avatar
Афтор_пиши_исчё *как раз хотел узнать работает ли фильтр инверсно или на прямую…
avatar
Есть урок по doclister + отдельная таблица?
Например, новости с алиасом, поиском и удобным редактированием в админке. Agel_Nash показывал, но там в админке было не доделано.
  • Shin
  • +1
avatar
avatar
Вот набросаю тут дегтя в мед)

Кроме того, что DocLister быстрее на большом количестве ресурсов и фильтр в нем лучше (как пишет ТС), в чем еще его преимущество настолько сильное, что мы указываем

&idType=`documents`
&documents=`1,2,3` 


вместо простого:

&parents=`3` или
&documents=`1,2,3` 


или что мы должны перечислять все используемые ТВ-параметры в DocLister (в Ditto такого нет).
avatar
idType — можно и не указывать. Тогда будет использоваться idType=`documents` если documents пуст. Или parents если он пуст, или текущий id в качестве parent подставится — вся логика как в Ditto. Вот только как себя должен вести сниппет если имеется вызов такой в котором getIDs вдруг вернет пустой результат?
[[Ditto? &parents=`[[getIDs]]`]]

Мы должны увидать «ничего не найдено» или список всех дочерних документов? Так что это вынужденная мера которая имеет свои преимущества — однозрачность вызова.

или что мы должны перечислять все используемые ТВ-параметры в DocLister
Да, это доставляет некий дискомфорт, т.к. нужно еще 1 параметр перечислять. Зато помимо более быстрой выборки, мы можем сразу понять какие ТВшки задействованы в чанках — не придется гадать какие шаблоны используют выбранные документы, затем смотреть какие ТВшки подключены к этим шаблонам… В общем опять прозрачность и однозначность вызовов, хотя если сайт делает и поддерживает один человек, то да, все это «лишнее».
avatar
Жень, я не говорю что доклистер плохой. Он классный и в некоторых моментах функциональнее дитто, правда расширений для него не хватает пока, но дело наживное. Просто для каждого решения свой инструмент со своими плюсами и минусами.
avatar
Я уже больше года только доклистером и пользуюсь — там и фильтры человеческие, и жрет намного меньше ресурсов. Про дитто уже и забыл что это такое (хотя иногда и приходится к нему возвращаться).
На визитке из 10 страниц разницы конечно никакой не будет :)) А вот на достаточно большом каталоге да с фильтрацией по нескольким ТВ да без кэширования вполне себе ощутимо становится.
Единственно что напрягает — это автоматический вывод только конечных ресурсов при указании &depth (т.е. не могу вывести несколько уровней папок) — хотя может просто не в курсе какого-то доп.параметра, который это может решить :))
avatar
Единственно что напрягает — это автоматический вывод только конечных ресурсов при указании &depth (т.е. не могу вывести несколько уровней папок) — хотя может просто не в курсе какого-то доп.параметра, который это может решить :))
оно?
avatar
А можно чуть подробнее? Иногда надо выводить из разных уровней глубины до n-ного всё, что не папки
avatar
так оно именно так и выводит при задании depth, а вот если надо вывести еще и папки разных уровней — такого я не нашел :)
avatar
Наверно не это. Бывает необходимость выводить именно папки, лежащие на разных уровнях — ну хотя бы все папки второго уровня. Но при задании &depth выводятся только «не папки» :)
avatar
[!DocLister? &parents=`0` &depth=`5` &showParent=`1` &addWhereList=`c.isfolder=1`!] — только папки (:
А если &depth=`2` и без &showParent, то получим только папки второго уровня.
Комментарий отредактирован 2014-10-16 16:04:07 пользователем Pathologic
avatar
Что-то глючит, подскажите, что не так делаю.
Сам каталог такой (в скобках — id):
Каталог (7)
. уровень 1.1 с картинкой в catimg;
… уровень 2;
… уровень 3.
. уровень 1.2 с картинкой в catimg.
Вывод Доклистера на странице верхнего уровня (Каталоге с id=7) такой:
[[DocLister?
&idType=`parents`
&parents=`7`
&tpl=`cats-list`
&tvList=`catimg`
&tvPrefix=``
&orderBy=``
&id=``
&filters=``
&depth=`1`
]]


Tpl такой:
<div class="mgoods-block1">
    <div id="icon-goods-block"></div>
	    <h3><a title="Перейти к каталогу [+menutitle+]" href="[~[+id+]~]">[+menutitle+]</a></h3>
        <p>[+introtext+]</p>
        <div class="big-icon-goods-block">
			<a href="[~[+id+]~]">
			    <img class="aligncenter size-full" title="[+menutitle+]" src="[+catimg+]" alt="[+menutitle+]" width="249" height="142" >
			</a>
	</div>
</div>

Вроде, должно выводить блоки уровень 1.1 и уровень 1.2, а выводит уровень 1.2 и уровень 2 (у него catimg пуст).
avatar
[[DocLister? &idType=`parents` &parents=`7` &tpl=`cats-list` &tvList=`catimg` &tvPrefix=``]]
avatar
Спасибо :)
avatar

Доброй ночи, подскажите пожалуйста, как мне вывести как на экране
т.е.
Есть каталог
В нем есть подкатегории и категории
Хочу вывести чтобы название подкатегорий было как ссылка, а сами товары уже которые лежат внутри, выводились уже с изображениями и ссылками.
Придумал как это сделать через Wayfinder, но хочу сделать через DocLister подскажите хотябы с чего начать и куда копать

Понимаю что через один шаблон невозможно все реализовать
Прошу помощи
  • dave
  • 0
avatar
Что-то какие-то перебои с сайтом=( дублирует сообщения
Комментарий отредактирован 2014-12-21 22:07:03 пользователем dave
  • dave
  • 0
avatar
Здравствуйте! DocLister — это класс!
А вот по «customTables — решение для хранения ресурсов MODxEvo в отдельных пользовательских таблицах» — разбираюсь пока только понемногу с этим — понимаю, что для спецов это все просто. Поэтому не пинайте старого котэ :-)
Подскажите, а если с отдельной базой работать, то например комменты прикрутить или тп что-нибудь — это дописывать как-то надо?
  • tmih
  • 0
avatar
С отдельной базой или таблицей?
Если просто вывод того что в отдельной таблице находится то дописывать не сильно много. А вот если еще и управление записями требуется, тогда дописывать много
avatar
Если просто вывод того что в отдельной таблице находится то дописывать не сильно много.
Ничего не нужно дописывать.

А вот если еще и управление записями требуется, тогда дописывать много
Не больше 100 строк.
avatar
Конкретно комментарии jot должны без проблем прикрутиться к отдельным таблицам, главное обозначить разные таблицы параметром tagid, чтоб при одних и тех же id из разных таблиц не пересекались комменты :)
А остальное [!JotX? &config=`tree` &docid=`[*custom_id*]` &tagid=`1` ...!] — и все дела, в шаблоне вывода объекта.
avatar
Спасибо товарищи за ответы! Да, действительно, это думал, про отдельную таблицу, попробую с комментами, если получиться, то опишу обязательно с картинками.
avatar
Товарищи, а кто знает blog.agel-nash.ru/addon/doclister.html это что-то случилось — только заглавная страница блога грузиться. Описание параметров осталось или только через вебархив?
avatar
я через вебархив добывал эту страницу
avatar
Протестил, JotX работает с другой таблицей на ура.

А как JoCo научить определять заголовок отдельной таблицы, а то он подставляет по id другой таблицы свое pagetitle из таблицы site_content? А если такого id в site_content нет, то вообще без заголовка. Все остальное JoCo выводит нормально.
avatar
blog.agel-nash.ru/addon/doclister.html
описания нет :(
avatar
На этом сайте в верхнем меню есть пункт «Документация MODX» — там в разделе сниппетов есть DocLister и кое что из того что было в блоге.
avatar
avatar
А подскажите есть какой-то аналог: &excludeDocs (Wayfinder) в DocLister
[!DocLister? &parents=`0` &depth=`5`!]
Хочу исключить некоторые страницы и их дочерние документы!
avatar
[!DocLister? &parents=`0` &depth=`5` &addWhereList=`c.id NOT IN (1,2,3)`!]

где 1,2,3 — документы которые нужно исключить
avatar
крутой костыль
avatar
почему это костыль? и как сделать не костылем?
avatar
как без костыля я не знаю, сразу говорю

а костыль, потому что условно вместо вычитания вы прибавляете отрицательные значения. работать будет, но как-то не красиво

вероятно, должен быть параметр &robwherelist или как-то так, т.е. прямой аналог exclude
avatar
Просто там нет некоторых, так сказать, утилит и вместо filter используется вот такой запрос
avatar
О боже. С каких пор MySQL стал костылем? Но если вы так авторитетно настаиваете, что addWhereList это костыль. То вот вам еще 2 костыля в копилку

$modx->runSnippet('DocLister', [
	'idType' => 'parents',
	'parents' => 1,	
	'exclude' => [21,19,17],
	'prepare' => function($data, $modx, $_DL){
		return (in_array($data['id'], $_DL->getCfgDef('exclude', []))) ? false : $data; 
	},
	'tpl' => '@CODE: [+id+]<br />'
]);

$modx->runSnippet('DocLister', [
	'idType' => 'parents',
	'parents' => 1,	
	'filters' => 'AND(content:id:notin:21,19,17)',
	'tpl' => '@CODE: [+id+]<br />'
]);
avatar
не принимайте близко к сердцу, мой комментарий не должен был никого обидеть

тем более, я вообще не представляю, как вы там все это написали — для меня это темный лес. я привык к WF — там есть параметр добавить страницы и удалить страницу. поэтому. мне и показалось не самым логичным решением указанное выше

все это лишь мнение дилетанта, не более
avatar
gregst , ваш комментарий никого и не обидел. Меня он наоборот повеселил, поднял настрой уставшему человеку :))

Это то же самое, как если бы вы написали, что PHP — костыль :))
avatar
Agel_Nash , :DD
avatar
Спасибо, но таким способом исключаются только документы с определенным id: 1, 2, 3
&addWhereList=`c.id NOT IN (1,2,3)`!]

а можно ли как-то добавить что бы помимо 1,2,3 исключались и все дочерние ресурсы документов 1,2,3. А то их все вручную перечислять очень долго :(
avatar
&addWhereList=`c.parent NOT IN (1,2,3)`

Так будут исключены дочерние для 1,2,3.

P.S. Но только чтобы это не вступило в противоречие с параметрами, заданными при вызове DocLister.
Комментарий отредактирован 2016-11-28 17:01:25 пользователем Aharito
avatar
Можно еще поиграться с параметром showParent, который понимает значения -1/0/1
avatar
Может быть глупый вопрос, можно ли передать «параметр» из вызова DocLister в шаблон (чанк) &tpl? К примеру, чтоб не плодить разные чанки tpl для разных списков (различающиеся классом), а просто при вызове передавать эту переменную.
avatar
То есть, к примеру, из
[!DocLister? &parents=`[+id+]`  &tpl=`dl.card`  !]
а чанк dl.card
<div class=" col-lg-4 col-md-3 ">[+title+]</div>
сделать что-то такое
[!DocLister? &parents=`[+id+]`  &tpl=`dl.card` &var=`col-lg-4 col-md-3`  !]
а чанк dl.card
<div class=" [+parametr+] ">[+title+]</div>
avatar
avatar
К сожаленью, я не программист, и в том, что по ссылке, мало понимаю (( Какой именно способ из перечисленных там Вы имеете в виду?
avatar
Я и сам не особо программист:

<?php
$data['parametr'] = $_DocLister->getCFGDef('var');
return $data;
avatar
Вы отличный программист, спасибо :)

Получилось так (решение в копилку):
1) Сниппет prepare_gridstyles
<?php
$data['gridstyles'] = $_DocLister->getCFGDef('gridstyles');
return $data;
2) Вызов DocLister
[!DocLister? &parents=`[+id+]`  &tpl=`dl.card` &prepare=`prepare_gridstyles` &gridstyles=` col-lg-4 col-md-3 ` !]
3) Чанк dl.card
<div class=" [+gridstyles+] ">[+title+]</div>
, и всё работает.
avatar
Единственное, если хочется несколько prepare — они пишутся через запятую?
&prepare=`prepare_gridstyles,prepare_height`
(почему-то не срабатывает)
avatar
Так сделайте все операции в одном. Зачем вам несколько?
avatar
Из соображений универсальности :)
Плюс, тк я не программист, для меня проблема даже объединить 2 одинаковых сниппета в 1 (
avatar
Должно работать через запятую, с prepare вроде ничего не правилось.
avatar
Да вот уж не знаю, по отдельности работает, а вместе при вот таком одинаковом коде нет :(
<?php
$data['gridstyles'] = $_DocLister->getCFGDef('gridstyles');
return $data;

<?php
$data['height'] = $_DocLister->getCFGDef('height');
return $data;
В вызове:
&prepare=`prepare_gridstyles, prepare_height`  &gridstyles=`col-xl-3` &height=`250` 
avatar
&prepare=`prepare_gridstyles,prepare_height`
avatar
Иногда один маленький пробел решает)) Спасибо.
avatar
Привет, напишите пожалуйста пример с фильтром: есть tv=`type`(дом, квартира, гараж и тд) — тип недвижимости, нужно в select option1=дом, option2=квартира, option3=гараж при выборе и нажатии кнопки фильтровать, не могу понять как все это сделать помогите. Не в одной документации нет простого примера только вызовы типа [[DocLister? &filters=`AND(content:content:containsOne: когда, наступит, мир)`]] а что толку от него…
Комментарий отредактирован 2017-02-10 05:27:43 пользователем one
  • one
  • 0
avatar
Подскажите может ли значение параметра DocLister браться из другого сниппета.
Например так &parents=`[[UltimateParent? &topLevel=`2`]]` работало в Ditto, в DocLister не работает?
avatar
Добрый день! Мучаюсь уже второй день, но у меня никак не хочет работать сортировка в eFilterResult. Пишу &orderBy=`pagetitle` &sortDir=`ASC`. Не пашет (((
avatar
Здравствуйте!
Попробуйте orderBy=`pagetitle ASC`
Вот тут поглядите docs.evo.im/03_extras/doclister/parametry_vyborki.html
avatar
Вот такой вот вызов, но все равно не работает

[!eFilterResult? 
&TplWrapPaginate=`@CODE:<div class="col-md-12"><nav aria-label="Page navigation"><ul class="pagination">[+wrap+]</ul></nav></div>`
&TplPage=`@CODE:<li><a href="[+link+]">[+num+]</a></li>`
&TplCurrentPage=`@CODE:<li class="active"><a href="[+link+]">[+num+]</a></li>`
&PrevNextAlwaysShow=`1`
&TplNextP=`@CODE:<li><a href="[+link+]">»</a></li>`
&TplNextP=`@CODE:<li><a href="[+link+]" aria-label="Вперед"><span aria-hidden="true">Вперед</span></a></li>`
&TplPrevP=`@CODE:<li><a href="[+link+]" aria-label="Назад"><span aria-hidden="true">Назад</span></a></li>`
&TplNext=`@CODE:<li><a href="[+link+]">»</a></li>`
&TplNextI=`@CODE:<li class="disabled"><a href="[+link+]" aria-label="Вперед"><span aria-hidden="true">Вперед</span></a></li>`
&TplPrevI=`@CODE:<li class="disabled"><a href="[+link+]" aria-label="Назад"><span aria-hidden="true">Назад</span></a></li>`
&depth=`1` 
&orderBy=`pagetitle DESC` 
&debug=`1` 
&paginate=`pages` 
&tpl=`property`
&display=`6`!]
avatar
&sortBy=`pagetitle` &sortOrder=`DESC`
только зачем задавать вопрос в теме про дитто и доклистер:)
Комментарий отредактирован 2018-02-09 20:31:45 пользователем webber
avatar
Добрый день! Подскажите, пожалуйста. У меня есть таблица, в которой на данный момент отображаются все дочерние документы родителя 3

[!DocLister? ¶nts=`3` &id=`listro` &paginate=`pages` &filters=`[!filters!]` &tpl=`dl.tovar_tpl` &tvList=`kol,kol_z,img_ro,pdf_file,doc_file,name_ro,groups,tip,lang,actual,cod,date_act` &noneTPL=`tpl_mistake` &sortBy=`date_act` &sortDir=`DESC` &dateFormat=`%d.%m.%Y` !]
Есть форма выборки данных. Выборка формируется в сниппете [!filters!]
Как сделать, чтобы по умолчанию таблица изначально не выдавала строк, а только при выборке?
avatar

$filters = $modx->runSnippet('filters');
if (!empty($filters)) {
    $params['filters'] = $filters;
    return $modx->runSnippet('DocLister', $params);
}
avatar
Спасибо большое)
avatar
Здравствуйте!
А вопрос — можете сниппет filters показать. Если это возможно, чтобы воспользоваться.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.