Блог на MODx Revolution: как сделать архив
Дорабатывая свой сайт, обнаружил, что на просторах отечественных интернетов тема MODx освещена весьма скудно, а там где освещена - в основном статьи по MODx Evolution, в то время как MODx Revolution широкой поступью набирает силу и мощь. Поэтому я решил написать несколько статей по MODx Revolution в ключе практических задач. Первая задача - организовать архив записей (фильтрацию по месяцам), как это сделано в небезызвестном Wordpress.
Начнем с начала: определимся с задачей и составим небольшую спецификацию, а-ля ТЗ.
Пользователь приходит на блог и просматривает записи. В специальном месте расположены ссылки на архивные записи по месяцам вида Декабрь 2010 (4), при нажатии на которую пользователю показываются только те блого-записи, которые были написаны в декабре 2010 года. В скобочках рядом с месяцем приведено количество записей за этот месяц (в данном примере - 4). Из описанного выше видно, что для наших целей необходимо каким-то образом передать выбранный месяц, пусть это будет параметр GET запроса с названием bymonth со значениями вида 201012, т.е. четыре цифры года и две цифры месяца. Также нам потребуется две функции, одна будет считать количество записей за месяц, проходя по всем блого-записям, чтобы сформировать ссыки архива, а другая - для выбора их базы данных только тех записей, которые были опубликованы в заданном месяце.
Сниппет getArchiveMonths для формирования ссылок архива:
$collection = $modx->getCollection('modResource', array(
'published' => 1,
'parent' => '2')
);
setlocale(LC_TIME, 'ru_RU.UTF8');
$output = "";
$months = array();
foreach ($collection as $resourceId => $resource) {
$strmonth = date("Ym", $resource->publishedon);
if(array_key_exists($strmonth, $months))
$months[$strmonth]['count']++;
else
{
$months[$strmonth]['count'] = 1;
$months[$strmonth]['text'] = strftime("%B %Y", $resource->publishedon);
}
}
krsort($months);
foreach ($months as $month => $count) {
$output .= $modx->getChunk($tpl, array(
'month' => $month,
'text' => $count['text'] . ' (' . $count['count'] . ')'
));
}
return $output;
В первом запросе мы получаем все документы, имеющие определенного родителя и опубликованные (при желании условия можно изменить, например на номер шаблона, который имеют блого-записи). Далее идет формирование словаря, ключом которого является месяц, а значением - пара значений: колчество записей в этот месяц и отформатированное название месяца. Потом этот словарь сортируется так, чтобы самые последние месяца шли раньше, и на его основе, а так же переданного чанка, генерируется кусок html-кода.
Вызов сниппета в моем случае (пробел между [ и [ сделан, чтобы MODx не обрабатывал его как вызов сниппета):
<ul>
[ [getArchiveMonths? &tpl=`archiveMonthRow`]]
</ul>
Пример чанка:
<li><a href="/blog/?bymonth="></a></li>
Прекрасно. Теперь у нас есть набор ссылок, по которым пользователь может нажать, осталось обработать эти запросы.
Т.к. для отображения документов в большинстве своем используется сниппет getResources, то для того, чтобы он показал лишь определенные записи достаточно задать ему параметр resources:
if (!empty($_GET['bymonth'])) {
$month = (int)$_GET['bymonth']; // для защиты от всякой дряни
$ids = $modx->runSnippet('getResourcesIds',array(
'month' => $month
));
$scriptProperties['resources'] = $ids;
}
Сниппет getResourcesIds возвращает список id ресурсов, опубликованных в заданном месяце:
$collection = $modx->getCollection('modResource', array(
"EXTRACT(YEAR_MONTH FROM FROM_UNIXTIME(`publishedon`)) = '$month'",
'published' => 1,
'parent' => '2'));
$output = "";
foreach ($collection as $resourceId => $resource) {
$output.=$resourceId.',';
}
if(strlen($output)>0)
$output = substr($output, 0, -1);
return $output;
Вот таким образом я решил вопрос с организацией архива на своем блоге. Самое забавное то, что в процессе работы над статьей, я наткнулся на уже готовое решение данной проблемы от комманды MODx, называется Archivist. Как я его не заметил несколько месяцев назад, когда делал сайт - уму непостижимо. Ну ничего. Изобрел свой велосипед - стал умнее и опытнее =)
Чт, 20.01.2011