[EVO] DLRequest - запуск сниппетов с параметрами из get/post

Сниппет разработан для замены Ditto с экстендером request по просьбе Extremum и на его же средства, за что большое спасибо.

Сниппет принимает значения из post или get-массива и использует их в качестве параметров для запуска другого сниппета. Изначально планировалась работа только с DocLister (отсюда и название), но в итоге можно вызывать любой сниппет. Тем не менее, наличие установленного DocLister'а обязательно.

DLRequest умеет не только передавать параметры, но и строить форму для управления этими самыми параметрами, без костылей типа:

<?php
//[!selected? ¶m=`ditto_id1_sortDir` &znach=`DESC`!]
if ($_REQUEST[$param]==$znach) {
echo "selected"; 
}
?>


Важный момент — возможные значения параметров задаются разработчиком, то есть если в форме для выбора количества документов на странице указано «10, 20, 50, 100», то подставить руками url?display=100500 не получится — такой параметр будет просто проигнорирован.

Предусмотрена также возможность сохранять значения параметров, которые передаются из браузера для других сниппетов, например, для DocLister это будет параметр page. То есть если в списке документов вы находитесь на странице 5, то после смены, например, направления сортировки, все равно останетесь на странице 5.

Теперь приведу пример вызова, из которого понятно, как это все работает:

[+paramsForm+]
<div>
[!DLRequest? 
&runSnippet=`DocLister` 
&parents=`2` 
&tpl=`@CODE:<p>[+id+]. [+pagetitle+]</p>` 
&paginate=`pages` 
&display=`0` 
&rqParams=`
    {
	"sortBy":{
            "id":"По id"
	    ,"pagetitle":"По pagetitle"
	}
	,"sortDir":{
	    "asc":"По возрастанию"
	    ,"desc":"По убыванию"
	}
	,"display":{
	    "1":"1 документ"
            ,"3":"3 документа"
            ,"5":"5 документов"
	}
    }
`
&rqParamsNames=`
    {
	"sortBy":"Сортировать по"
	,"sortDir":"Порядок"
	,"display":"Результатов на странице"
    }
`
&selectedClassName=`selected`
& paramsForm=`paramsForm`
&keepParams=`page`
& paramsOwnerTPL=`@CODE
    <form method="get" action="[~[*id*]~]">
        [+keepParams+]
	[+params+]
        <button type="submit">Отправить</button>
    </form>
`
& param.ownerTPL=`@CODE:
    <label>[+description+]</label>
	
    <select name="[+paramName+]">
	[+values+]
    </select>
`
& param.tpl=`@CODE:
    <option value="[+value+]" [+selectedClass+]>
        [+description+]
    </option>
`
&sortBy.tpl=`@CODE:
    <option value="[+value+]" [+selectedClass+]>
        [+description+] dfdfdfh
    </option>
`
&display.ownerTPL=`@CODE:
    <label style="color:red;">[+description+]</label>
	
    <select name="[+paramName+]">
	[+values+]
    </select>
`
&keepTpl=`@CODE:
    <input name="[+paramName+]" value="[+value+]" type="hidden">
`
!]
</div>
[+pages+]

После & пробелы стоят, потому что иначе редактор подменяет символы.

Комментарии к примеру, а также сам сниппет — github.com/Pathologic/DLRequest

29 комментариев

avatar
А есть демка как это все работает?
А если запускать с eFilter, то тут так будет?
&runSnippet=`eFilterResult` 
avatar
В принципе да, но нужно еще править как минимум js в eFilter. Сейчас как раз вожусь для Extremum .
avatar
В общем, с eFilter самое простое решение это поместить в его форму поля DLRequest. В конфиге eFilter пишем:

$tplFilterForm = '[+wrapper+]';

А в шаблоне страницы что-то типа:

<form id="eFiltr" class="eFiltr eFiltr_form" action="[~[*id*]~]" method="get">
[+eFilter_form+]
...
[+paramsForm+]
</form>

Ну и убрать form из ¶msOwnerTPL.
Тогда работает все без правок js. Но если переписать js, то будет работать еще лучше (:
avatar
Надо подмешивать параметры в вызов eFilterResult — github.com/webber12/eFilter/blob/master/install/assets/snippets/snippet.eFilterResult.tpl#L116 — именно он через DocLister занимается выводом найденных после фильтрации документов.

Сам eFilter сортировкой не занимается, он формирует нужную форму и отдает список id подходящих документов в плейсхолдер.
avatar
Так DLRequest и подмешивает, тут дело в другом было — чтобы не слетали настройки сортировки при фильтрации. Кстати, можно отключить загрузку скриптов и стилей eFilter?
Комментарий отредактирован 2015-06-11 07:56:33 пользователем Pathologic
avatar
Вам бы вдвоем с webber совместить усилия и выпустить классный продукт)
avatar
Только закомментировать в сниппете :)) Хотя там стили с префиксами, так что особо они мешать не должны.
avatar
попробовал, чет у меня не получилось так

Просто ничего не появляется — ни ошибок, ни select-ов с параметрами сортировки
MODx 1.2.1-d9.1.0
DLRequest 1.0.0
DocLister 2.3.0
eFilter 0.1
Комментарий отредактирован 2017-01-15 13:06:22 пользователем zloyxrom
avatar
вот такой вызов
[!eFilter?  &hide_zero=`1` !]	
[!DLRequest? 
	&runSnippet=`eFilterResult` 
	&tpl=`tovarTpl` 
	&parents=`[*id*]` 
	&depth=`3`
	&display=`35` 
	&tvList=`image,price`
	&orderby=`menuindex ASC`
	&paginate=`1`
	&TplNextP=`TplNextP`
	&TplPrevP=`TplPrevP`
	&TplPage=`TplPage`
	&TplCurrentPage=`TplCurrentPage`
	&TplWrapPaginate=`TplWrapPaginate`
	&tvPrefix=``  
	&tvSortType=`SIGNED`
	&orderBy=`menuindex ASC`
	&rqParams=`
	{
	"orderBy":{
	"menuindex ASC":"выбрать"
	,"price ASC":"цена по возрастанию"
	,"price DESC":"цена по убыванию"
	,"pagetitle ASC":"по алфавиту А -> Я"
	,"pagetitle DESC":"по алфавиту Я -> А"
	}
	,"display":{
	"12":"12","50":"50","100":"100","all":"все"
	}
		}
	`
	//описания параметров
	&rqParamsNames=`
	{
	"orderBy":"Сортировка"
	,"display":"Товаров на странице по"
	}
	`
	&selectedClassName=`selected`
	//плейсхолдер для вывода формы
	¶msForm=`paramsForm`
	//можно сохранять произвольные параметры от других сниппетов
	&keepParams=`page`
	//шаблон формы 
	¶msOwnerTPL=`
	[+keepParams+]
	[+params+]
	`
	//общий для всех параметров шаблон
	¶m.ownerTPL=`
	<p class="pull-right">
		<label>[+description+]</label> 
		<select name="[+paramName+]" onchange="this.form.submit();">
			[+values+]
		</select>
	</p>
	`
	//общий шаблон для значений параметра
	¶m.tpl=`
	<option value="[+value+]" [+selectedClass+]>[+description+]</option>
	`
	//можно для каждого параметра задавать свои шаблоны
	&orderBy.tpl=`
	<option value="[+value+]" [+selectedClass+]>[+description+]</option>
	`
	&display.ownerTPL=`
	<p class="pull-left">
		<label >[+description+]</label> 
		<select name="[+paramName+]" onchange="this.form.submit();">
			[+values+]
		</select>
	</p>
	`
	//шаблон для внешних параметров
	&keepTpl=`
	<input name="[+paramName+]" value="[+value+]" type="hidden" id="keep">
	`
	!]														
Комментарий отредактирован 2017-01-15 13:14:53 пользователем zloyxrom
avatar
И еще один вопрос, результаты в куки попадают, то есть при переключении пагинатора результаты не слетают?
avatar
DocLister сохраняет get-параметры, когда строит ссылки, поэтому не слетают. Если другие сниппеты так не делают, то это пусть на их совести уже будет.
avatar
Протестил, работает, но возник такой вопрос.
А если надо сортировать не по id или pagetitlle, а по TV-параметрам?
Например, сайт недвижимости, и надо отсортировать объекты недвижимости по цене или (и) по площади.
Если все объекты недвижимости в одной категории, то все нормально. А если в категории есть еще подкатегории, то сортировка получается не сквозная, а по подкатегориям (визуально получается каша).
avatar
tv price допустим, то
"sortBy":{
            "price":"По цене"
            ,"pagetitle":"По pagetitle"
        }


должно работать.
avatar
Да это понятно, оно и работает. Но работает так как я написал выше в последнем абзаце.
avatar
DLRequest не обрабатывает параметры, а просто передает их в другой сниппет, поэтому для сложной сортировки можно сделать типа прослойку:
<code>
&rqParams=`
    {
        "sortByArea":{
            "asc":"По возрастанию"
            ,"desc":"По убыванию"
        }
        ,"sortByPrice":{
            "asc":"По возрастанию"
            ,"desc":"По убыванию"
        }
    }
`
&runSnippet=`prepareOrderBy`
</code>
<code>
//prepareOrderBy
$orderBy = array();
if (isset($params['sortByArea'])) $orderBy[]='area '.$params['sortByArea'];
if (isset($params['sortByPrice'])) $orderBy[]='price '.$params['sortByPrice'];
$params['orderBy'] = implode(',',$orderBy);
return $modx->runSnippet('DocLister',$params);
</code>
Еще можно загрузить класс, в котором переопределяются методы класса \DLRequest\DLRequest и указать название этого класса в параметре &DLRController.

И еще один вариант — плагин на событие onParseProperties вместо сниппета-прослойки.
Комментарий отредактирован 2015-06-15 17:50:31 пользователем Pathologic
avatar
Возможно я не прав, но мне кажется, что это сам DocLister так работает.
Делаю вот такой вызов
[!DocLister? &tvPrefix=`` &display=`30` &parents=`[*id*]`  &depth=`3` &paginate=`pages` &orderBy=`price ASC`  &tpl=`item_tpl` &tvList=`img,price`!]

и он сортирует по подкатегориям по очереди.
А если задаю сортировку по id
[!DocLister? &tvPrefix=`` &display=`30` &parents=`[*id*]`  &depth=`3` &paginate=`pages` &orderBy=`id ASC`  &tpl=`item_tpl` &tvList=`img,price`!]

то сортировку дает сквозную.
Или я DocLister еще плохо освоил(
avatar
Может нужно orderBy=`parent ASC,id ASC`? Я что-то не очень понимаю, что значит сквозная сортировка (:
avatar
Каталог выглядит так

Категория
подкатегория1
-товар1 id=1 price=100
-товар2 id=2 price=170
-товар3 id=10 price=90
подкатегория2
-товар4 id=20 price=150
-товар5 id=4 price=140

Если задать сортировку по id ASC, то на странице «Категория» все товары выводятся по id по возрастанию, не зависимо, в какой подкатегории они находятся. Я и назвал этот вариант сквозным:

-товар1 id=1 price=100
-товар2 id=2 price=170
-товар5 id=4 price=140
-товар3 id=10 price=90
-товар4 id=20 price=150

А вот если задать сортировку price ASC, то сначала выводятся товары из подкатегории 1 с возрастанием цены, а потом с подкатегории 2 с возрастанием цены:

-товар3 id=10 price=90
-товар1 id=1 price=100
-товар2 id=2 price=170
-товар5 id=4 price=140
-товар4 id=20 price=150

А хочется, и должно быть так

-товар3 id=10 price=90
-товар1 id=1 price=100
-товар5 id=4 price=140
-товар4 id=20 price=150
-товар2 id=2 price=170
avatar

tovar 1 — 100
tovar 2 — 170
tovar 3 — 90
tovar 5 — 150
tovar 4 — 140

[!DocLister? &tvPrefix=`` &display=`30` &parents=`[*id*]`  &depth=`3` &paginate=`pages` &orderBy=`price ASC` &tvSortType=`SIGNED` &tpl=`@CODE:[+id+]. [+price+]
` &tvList=`price`!]

Результат:

22. 90
16. 100
23. 140
21. 150
17. 170
avatar
Спасибо, сейчас все ОК, дело в
&tvSortType=`SIGNED`

надо будет почаще читать буквари)) здесь тоже есть
blog.agel-nash.ru/addon/doclister.html
avatar
Нормально DocLister сортирует по цене — возможно вы просто не указали
&tvSortType=`UNSIGNED`
и вам кажется что что-то не так сортируется.
В самом DLRequest что-то нигде не обнаружил этого параметра тоже — возможно, не там искал, возможно — надо поправить :)
avatar
В смысле? Все параметры, с которыми вызывается DLRequest, передаются в runSnippet.
avatar
Спасибо
вот только не понял в чем разница SIGNED и UNSIGNED?
avatar
Unsigned — для целых от 0, signed — учитывает и знак (т.е. и для отрицательных целых). Т.к. цены (да и все остальное) у нас обычно больше 0 и Unsigned для этих целей в два раза больший имеет диапазон — я обычно использую его :)
avatar
Понял, спасибо.
avatar
Как передать &filters=`OR(tv:params:like:50;tv:params:like:52)` + выбор параметров чекбоксами
Комментарий отредактирован 2016-08-24 10:20:03 пользователем zloyxrom
avatar
получается передать только одно значение в ?filters=
avatar
Да, когда много значений в параметре, то уже не получится просто. Можно сделать еще один сниппет, как выше написано.
avatar
Добрый день. Пишу вот такую конструкцию &sortType=`other`
&orderBy=`RAND()`, но сортировка не срабатывает, после обновления страницы одно и то же. Что я делаю не так?
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.