[РЕШЕНО] Фильтрация LIKE в DocLister

Всем здравствуйте!
Прошу помощь.

Суть проблемы.
Есть сайт, в котором 2 каталога. Первый — экскурсии, второй — достопримечательности.

При создании новой экскурсии формируется маршрут из достопримечательностей — с помощью PickDocsInTree в ТВ-параметр marsh записывается перечень нужных id. А на странице одной экскурсии достопримечательности выводятся так

[!DocLister? &tvPrefix=`` &idType=`documents` &documents=`[*marsh*]` &jotcount=`1` &summary=`notags,len:140` &sortType=`doclist` &tvList=`img,price` &tpl=`item_tpl`!]

Здесь все ОК, вопросов нет.

Теперь надо сделать обратную задачу — на странице каждой достопримечательности вывести все экскурсии, в которых она присутствует.
Вывожу так

[!DocLister? &tvPrefix=`` &depth=`3` &parents=`51` &jotcount=`1` &summary=`notags,len:140` &filters=`AND(tv:marsh:like:[*id*])` &summary=`notags,len:240` &orderBy=`pagetitle ASC` &tvList=`img,price,marsh` &tpl=`item_tpl`!]

Выводит, но радовался не долго.
Оказывается, что если достопримечательность имеет id=34, то выводятся все экскурсии, у которых в ТВ marsh записаны не только id=34, но и id=134.

Прошу подсказать, как правильно отфильтровать и корректно вывести?

Спасибо.

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

avatar
Лучше было бы создать таблицу связей с двумя колонками: id достопримечательности — id экскурсии.
avatar
Спасибо. К сожалению, на этапе разработки не додумал и эту особенность не заметил, а сейчас сайт уже заполнен (( трудно представляю, как это можно обыграть на живом сайте… может есть какие-то другие варианты?
avatar
вначале что-то написал много букав про то что через IF проверять и в последуещем выводить (но понял что бред)- попробывал найти более менее документацию(как то тоже не сложилось). Возник такой вопрос почему LIKE (ведь он как раз таки и подразумевает совпадение чати, а не полное — если я не ошибаюсь) попробовать другой тип фильтрации (EQ, IS, :=:)
думаю в данном комменте Agel_Nash дал нужный ответ
Комментарий отредактирован 2016-04-22 08:23:21 пользователем fractal-zbk
avatar
like потому что id — это одно число, например 34, а ТВ — это много чисел через запятую, например 37,34,49,128,315… и нужно проверить, если в этом списке число, равное id, и если есть — вытащить соответствующий документ
avatar
попробуйте такой вариант решения:
1) сделайте сниппет обертку для DocLister
2) получаете список документов:

$id = 100;

$tmplvarid = 7;

$find = " AND FIND_IN_SET('".$id."', value)>0 "; // если id хранятся в виде 98,99,100

$find = " AND FIND_IN_SET('".$id."', REPLACE(value, ' ', ''))>0 "; // если id хранятся в виде 98 ,99 ,100

$res = $modx->db->select(
    'contentid', 
    $modx->getFullTableName('site_tmplvar_contentvalues'), 
    "tmplvarid=".$tmplvarid." ".$find
);


3) передаете список id в runSnippet для DocLister
avatar
спасибо, попробую
avatar
Спасибо, идея с FIND_IN_SET помогла!
Решился вопрос так.
Сниппет num

<?php
global $modx;
$id = $id;
$tmplvarid = '16';
$table = $modx->getFullTableName('site_tmplvar_contentvalues');
$find = " AND FIND_IN_SET('".$id."', value)>0 ";
$res = $modx->db->query("SELECT contentid FROM $table WHERE tmplvarid='$tmplvarid' $find");
$output = '';
while ($row=$modx->db->getRow($res)) {
    $ids[] = $row['contentid'];
        $str = implode(',', $ids);
}
return $str;
?>

и соответственно вывод обратной задачи

 [!DocLister? &tvPrefix=`` &idType=`documents` &documents=`[[num? &id=`[*id*]`]]` &jotcount=`1` &summary=`notags,len:140` &sortType=`doclist` &tvList=`img,price` &tpl=`item_tpl`!]
avatar
avatar
Спасибо, давно точу зуб примненить это Ваше дополнение, но пока оказии не случалось. И в данном случае о TagSaver тоже вспомнил, но уаы, это уже было после того как…
но в следующий раз учту.
avatar
Ничего не мешает внедрить это решение на сайт, где уже имеются записи. От вас требуется лишь пересохранить документы после настройки плагина. И то, пересохранить документы можно массовов скриптом при помощи MODxAPI
avatar
Кроме вышеупомянутых способов можно ещё фильтровать в ditto-стиле, через prepare-сниппет вроде такого:
<?php
$filterKey = $_DocLister->getCFGDef('filterKey', 'category');
$filterValue = $_DocLister->getCFGDef('filterValue', $modx->documentObject['category'][1]);
if (empty($data[$filterKey]) || !array_intersect(explode(',',$filterValue),explode(',',$data[$filterKey]))) return false;
return serialize($data);
?>

Ну и потом соответственно:
[[DocLister? &prepare=`dlFilter` &filterKey=`marsh` &filterValue=`[*id*]` ... ]]

А если, к примеру, понадобится выбор родительских папок (групп достопримечательностей):
&filterValue=`[*id*],[[parents]]`
avatar
Спасибо, интересная идея по группам, на будущих проектах испытаю
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.