Навигация по автометкам
Хочу поделиться своим способом работы с метками, для дополнительной навигации по ресурсам. Вообще то, для этого уже есть tagLister, но мне нравится контролировать процесс. И вообще, это мой первый пост тут, так что сильно не пинайте :)

Для создания, собственно меток, логично использовать штатный tv параметр с типом autotag (автометка), поэтому вначале, создаю его и как нибудь называю. Не задумываясь особенно, назвал его по названию типа — autotag. Добавляю созданный tv в шаблон для вывода постов и с ним — все.

Для вывода меток, делаю два сниппета, один для создания облака меток — tagCloud, второй для вывода меток в блоге и в самом посте — tagLinks.
tagCloud:
Этот сниппет выводит список уникальных значений меток, в виде ссылок, с GET параметром, который потом будет использоваться, для фильтрации вывода ресурсов:
Что в нем происходит:
Из таблицы с классом «modTemplateVarResource», выбираю все tv с типом «autotag» и именем «autotag», связанные с ресурсами находящимися в текущем контексте, родителем для которых, в случае вывода в блоге, является ресурс где вызывается сниппет, а в случае вывода в статье — родитель статьи. Так как в одной автометке, может быть много значений, перечисленных через запятую, то сначала, на уровне запроса, убираю повторяющиеся множественные значения, затем разбиваю результирующий массив по запятым и из него, так же, убираю повторяющиеся значения. В конце формирую ссылки.
tagLinks:
Этот сниппет, выводит список ссылок, для блога и ресурса, а так же передает GET-параметр в вызов pdoResources, для фильтрации по меткам. В принципе, это разные задачи, но я решил не плодить сниппеты.
Что в нем происходит:
Сниппет может принимать в качестве параметров два значения:
В первом случае, сниппет разбивает полученную автометку на отдельные значения, заворачивает их в ссылки, как в tagCloud и выводит. Для того, чтобы можно было выводить метки и в блоге и в самой статье, в начале сниппета получаю расширение для типа html и проверяю его наличие в адресной строке. Если адрес заканчивается на .html, то в url попадает адрес родителя (для статьи).


Во втором случае, когда передается параметр &get=`1`, сниппет смотрит в адресную строку и если там есть значение метки, то передает его в вывод, оформляя подходящим для фильтрации образом.
А вот вызов pdoResources, для создания блога и фильтрации по автометке.
На уникальность не претендую :)
UPD.
Если захотелось вывести, например в сайдбаре, статьи связанные с текущей, по меткам, то можно использовать вот такой сниппет
tagRelated:
Здесь, я выбираю записи из таблицы с классом modResource, с которыми связана автометка имеющая, хотя бы одно значение, такое же как у текущей.
Вызов:
Чанк RELATED:
Для создания, собственно меток, логично использовать штатный tv параметр с типом autotag (автометка), поэтому вначале, создаю его и как нибудь называю. Не задумываясь особенно, назвал его по названию типа — autotag. Добавляю созданный tv в шаблон для вывода постов и с ним — все.
Для вывода меток, делаю два сниппета, один для создания облака меток — tagCloud, второй для вывода меток в блоге и в самом посте — tagLinks.
tagCloud:
<?php
$base = $modx->config['base_url'];
$tvname = $modx->getOption('tvname', $scriptProperties, "autotag");
$output = "";
$content_type = $modx->getObject('modContentType', array('mime_type' => 'text/html'));
if(substr_count($_SERVER["REQUEST_URI"], $content_type->get('file_extensions'))) {
$parent = $modx->resource->parent;
$url = $modx->makeUrl($modx->resource->parent);
}else{
$parent = $modx->resource->id;
$url = $modx->resource->uri;
}
$q = $modx->newQuery('modTemplateVarResource');
$q->select('DISTINCT(`modTemplateVarResource`.`value`)');
$q->innerJoin('modTemplateVar', 'tv', "tv.id = modTemplateVarResource.tmplvarid");
$q->innerJoin('modResource', 'res', 'res.id=modTemplateVarResource.contentid');
$q->where(array(
'tv.name' => $tvname,
'res.context_key' => $modx->resource->context_key,
'res.parent' => $parent
)
);
if($q->prepare() && $q->stmt->execute()) {
while ($row = $q->stmt->fetch(PDO::FETCH_ASSOC)) {
$result[] = $row['value'];
}
}
if($result) {
$result = implode($result, ',');
$result = array_unique(explode(',', $result));
foreach($result as $value) {
$output .= "<a href='{$base}{$url}?tag={$value}'>{$value}</a> ";
}
}
return $output;Этот сниппет выводит список уникальных значений меток, в виде ссылок, с GET параметром, который потом будет использоваться, для фильтрации вывода ресурсов:
[[!tagCloud:default=`Пока нет меток`? &tvname=`autotag`]]
<a href="/path/?tag=метка">метка</a>
<a href="/path/?tag=опятьметка">опятьметка</a>
<a href="/path/?tag=ещеметка">ещеметка</a>Что в нем происходит:
Из таблицы с классом «modTemplateVarResource», выбираю все tv с типом «autotag» и именем «autotag», связанные с ресурсами находящимися в текущем контексте, родителем для которых, в случае вывода в блоге, является ресурс где вызывается сниппет, а в случае вывода в статье — родитель статьи. Так как в одной автометке, может быть много значений, перечисленных через запятую, то сначала, на уровне запроса, убираю повторяющиеся множественные значения, затем разбиваю результирующий массив по запятым и из него, так же, убираю повторяющиеся значения. В конце формирую ссылки.
tagLinks:
<?php
$tags = $modx->getOption('tags', $scriptProperties);
$get = $modx->getOption('get', $scriptProperties, '0');
$base = $modx->config['base_url'];
$content_type = $modx->getObject('modContentType', array('mime_type' => 'text/html'));
if(substr_count($_SERVER["REQUEST_URI"], $content_type->get('file_extensions'))) {
$url = $modx->makeUrl($modx->resource->parent);
}else{
$url = $modx->resource->uri;
}
if(!$get){
if(!$tags) {return '';}
$tags = explode(',',$tags);
foreach($tags as $value) {
$output[] = "<a href='{$base}{$url}?tag={$value}'>{$value}</a>";
}
return implode(' ',$output);
}else{
return (!empty($_GET['tag']))? "autotag==%{$_GET['tag']}%" : '';
}Этот сниппет, выводит список ссылок, для блога и ресурса, а так же передает GET-параметр в вызов pdoResources, для фильтрации по меткам. В принципе, это разные задачи, но я решил не плодить сниппеты.
Что в нем происходит:
Сниппет может принимать в качестве параметров два значения:
[[!tagLinks? &tags=`[[*autotag]]`]]
и
[[!tagLinks? &get=`1`]] В первом случае, сниппет разбивает полученную автометку на отдельные значения, заворачивает их в ссылки, как в tagCloud и выводит. Для того, чтобы можно было выводить метки и в блоге и в самой статье, в начале сниппета получаю расширение для типа html и проверяю его наличие в адресной строке. Если адрес заканчивается на .html, то в url попадает адрес родителя (для статьи).
Во втором случае, когда передается параметр &get=`1`, сниппет смотрит в адресную строку и если там есть значение метки, то передает его в вывод, оформляя подходящим для фильтрации образом.
А вот вызов pdoResources, для создания блога и фильтрации по автометке.
[[!pdoResources?
&parents=`[[*id]]`
&tvFilters=`[[!tagLinks? &get=`1`]]`
&tpl=`@INLINE <div class="row">
<div class="cols col-10 intro">
<h2><a href="{{+link}}">{{+pagetitle}}</a> ({{+publishedon}})</h2>
<div>{{!tagLinks? &tags=`{{+tv.autotag}}`}}</div>
{{+introtext}} <a href="{{+link}}">читать дальше..</a>
</div>
</div>`
]]На уникальность не претендую :)
UPD.
Если захотелось вывести, например в сайдбаре, статьи связанные с текущей, по меткам, то можно использовать вот такой сниппет
tagRelated:
<?php
$tpl = $modx->getOption('tpl', $scriptProperties);
$limit = $modx->getOption('limit', $scriptProperties, 5);
$tvname = $modx->getOption('tvname', $scriptProperties, "autotag");
$tvvalue = $modx->resource->getTVValue($tvname);
$base = $base = $modx->config['base_url'];
$currentid = $modx->resource->id;
$output = '';
$q = $modx->newQuery('modResource', array(
'context_key' => $modx->resource->context_key,
'parent' => $modx->resource->parent
));
$q->select('pagetitle,introtext,publishedon,uri,tvres.value as autotag');
$q->innerJoin('modTemplateVarResource', 'tvres', "tvres.contentid = modResource.id");
$q->innerJoin('modTemplateVar', 'tv', "tv.id = tvres.tmplvarid");
$q->limit($limit);
$q->where(array(
'modResource.id:!=' => $currentid,
'tv.name' => $tvname,
'tvres.value:REGEXP' => str_replace( ',', '|', $tvvalue)
)
);
if($q->prepare() && $q->stmt->execute()) {
while ($row = $q->stmt->fetch(PDO::FETCH_ASSOC)) {
$output .= $modx->getChunk($tpl, array(
'url' => $base.$row['uri'],
'date' => date("Y-m-d H:i:s", $row['publishedon']),
'pagetitle' => $row['pagetitle'],
'text' => $row['introtext']
));
}
}
return $output;Здесь, я выбираю записи из таблицы с классом modResource, с которыми связана автометка имеющая, хотя бы одно значение, такое же как у текущей.
Вызов:
[[!tagRelated:default=`Пока нет связанных постов`?
&tpl=`RELATED`
&limit=`4`
&tvname=`autotag`
]]Чанк RELATED:
<div>
<a href="[[+url]]">[[+pagetitle]]</a> <span class="date">[[+date]]</span><br />
<div class="sidetext">[[+text:notags:ellipsis=`100`]]</div>
</div> Комментарии: 23
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
Один вопрос, можно ли указать контейнер ресурсов, чтобы на странице со статьёй тоже облако тегов отображалось?
В таком случае все отлично фильтрует, но тогда чистый блог не выводит совсем.
Тоже не показывает в статьях, как и tagLinks, если закомментировать несколько строчек, то всё ок.
кусок tagLinks
И аналогично у tagCloud:
Для мультиязычности Babel используется?
Настройки как по мануалу?
Плагин переключающий контексты:
Сниппет переключающий языки:
Настройки контекстов:
Настройки системы -> Babel
Тег base в начале странички:
Но повторюсь, кол-во таких ТВ было большое
Само собой, напрашивается: tagLinks урезаем, делаем HashtagLinks
[[!HashtagLinks? &tags=`[[*tags]]`]]
Одно досадно, предзаполнять поле комментариев по ogp.me/ не предусмотрено, а в <meta property=«og:description» content="[[!HashtagLinks? &tags=`[[*tags]]`]] добавлять бессмысленно, что сводит все на нет, т.е. постинг хэш-тегов в комментарии вручную.
Может у кого есть мысли как реализовать автопостинг и хэштэгов тоже?
Я использовал раньше такой вариант taglist
Вызывал pdopage и в чанке прописывал так:
Все прекрасно работало, но вот сейчас перенес все тэги из TV в поле description.
Надеялся что замена
на
поможет, но в чанк
передается только дескрипшен той странице на которой вызывается, а не того ресурса который передается из pdopage.
Подскажите как быть?
Вывод осуществлять с помощью pdoPage с фильтрацией &tvFilters=`тег`.
Облако тегов будет — вывод всех ресурсов из созданного раздела — TEG.
Встанет проблема как вывести теги (ссылки) принадлежащие одной статье. Можно использовать taglister, но он будет формировать свои ссылки, которые нам не нужны. Можно попробовать подменять их с помощью компонента redirector, направлять на наши созданные ресурсы, вместо ссылок taglister.
Сам пока не реализовывал, но другого варианта пока не нашел. А title и description для страниц вывода материалов по тегам, вещь нужная и полезная, можно получить дополнительных посетителей, поисковики сейчас любят когда у вас подборка материалов по теме, раскрывающая ее (но правильное оформление страницы — обязательно).
Минус решения — трудоемко и страницы, с тегами придется создавать ручками. Как бы автоматизировать…
Ну и предыдущую логику тоже придется немного переделать.
Посмотреть демо или скачать бекап демо есть возможность??
Не все получилось.
Хотелось бы до конца разобраться.
sasha.tumanov