Генерация расписания занятий на pdoTools
Увидел недавно вопрос на сообществе — человек хочет сгенерировать таблицу с расписанием занятий по дням.
Казалось бы, задача несложная, но это совсем не так. Стандартные сниппеты не предназначены для такой работы и их приходится запускать на каждый день недели. И даже если вас не волнует скорость работы, то в итоговой таблице будут пропущенные ячейки, что совсем не айс.
Можно сделать свой компонент расписаний, но это нужно далеко не всем, тем более, для вывода всего одной недели из дерева.
Поэтому предлагаю вам готовое решение, а заодно и демонстрацию работы с pdoTools. Конечно, можно было бы обойтись и родными методами MODX, но с ним быстрее.
Все нужные данные выбираются за один запрос, а дальше очень быстрая обработка и оформление на PHP.
Вызов на странице:
<table border="1" cellpadding="5">
<thead>
<tr>
<th>Понедельник</th>
<th>Вторник</th>
<th>Среда</th>
<th>Четверг</th>
<th>Пятница</th>
<th>Суббота</th>
<th>Воскресенье</th>
</tr>
</thead>
<tbody>
[[!pdoSchedule?
&start=`2`
&tpl=`@INLINE <td><a href="/[[+uri]]">[[+pagetitle]]</a></td>`
&tplEmpty=`@INLINE <td> </td>`
&tplRow=`@INLINE <tr>[[+days]]</tr>`
]]
</tbody>
</table>
Сниппет pdoSchedule:
<?php
// Подключаем pdoFetch, потому что нам нужно работать с БД
$pdo = $modx->getService('pdoFetch');
// Задаем условия выборки: опубликованные ресурсы, потомки указанного родителя
$parents = $modx->getChildIds($start, 1);
$where = array(
'published' => 1,
'deleted' => 0,
'parent:IN' => $parents
);
// Дополнительные параметры для выборки
$options = array(
// Присоединяем родителей ресурсов (дни недели)
'innerJoin' => array(
'Parent' => array(
'class' => 'modResource',
'alias' => 'Parent',
'on' => 'Parent.id = modResource.parent'
)
)
,'select' => array(
'modResource' => 'all',
// И выбираем их индекс
'Parent' => 'Parent.menuindex as dow'
)
// Указываем сортировку результатов по индексу документа внутри дня
,'sortby' => 'menuindex,dow'
,'sortdir' => 'asc'
,'includeTVs' => !empty($includeTVs) ? $includeTVs : ''
);
// Выбираем ресурсы, подходящие под условия
$collection = $pdo->getCollection('modResource', $where, $options);
// Оформляем их как массив дней недели, используя индекс дней (поле dow)
$week = array();
foreach ($collection as $v) {
if (!isset($week[$v['dow']])) {
$week[$v['dow']] = array();
}
$week[$v['dow']][] = $v;
}
// Осталось только оформить дни в строки таблицы
$output = $days = '';
// Бесконечный цикл
while (true) {
$in = 0;
// Для перебора под дням недели
for ($i = 0; $i <= 6; $i++) {
// Если день еще не пуст
if (!empty($week[$i])) {
// Забираем первый элемент массива в нём
$days .= $pdo->getChunk($tpl, array_shift($week[$i]));
// И плюсуем индиктор того, что строка не пустая
$in++;
}
// Иначе вставляем пустую ячейку
else {
$days .= $pdo->getChunk($tplEmpty);
}
}
// Если у нас строка с днями - добавляем ее в результаты
if ($in) {
$output .= $pdo->getChunk($tplRow, array('days' => $days));
// И обнуляем дни для следующей строки
$days = '';
}
// А если документы закончились - пора выходить из цикла
else {
break;
}
}
// Возвращаем оформленные ряды таблицы
return $output;
Результат:
Дни недели можно спокойно переименовывать, а документы внутри менять местами. Все привязано к индексу, а не названиям.
Думаю, комментариев в коде вполне достаточно. Если есть вопросы — задавайте.
Комментарии: 28
Красиво. С бесконечным циклом понравилось.
Круто, с комментариями целый урок получился!
Думаю для решения этой задачи было бы практичнее использовать MIGX. Один документ без всяких вложений, с возможностью наглядного редактирования и сортировкой.
Две причины:
1. Это ответ на конкретно поставленный вопрос. Человек спросил про вывод ресурсов в виде календаря.
2. Мне не нравится MIGX. На мой взгляд — это один большой костыль для тех, кому лень писать свои компоненты и работать напрямую с таблицами.
Когда у меня возникла такая задача на atletik-city.ru — я решил это написанием удобного компонента и он до сих пор работает. Там, конечно, побольше функций.
1. Это ответ на конкретно поставленный вопрос. Человек спросил про вывод ресурсов в виде календаря.
2. Мне не нравится MIGX. На мой взгляд — это один большой костыль для тех, кому лень писать свои компоненты и работать напрямую с таблицами.
Когда у меня возникла такая задача на atletik-city.ru — я решил это написанием удобного компонента и он до сих пор работает. Там, конечно, побольше функций.
Василий, безусловно ты прав и по первому и по второму вопросу, я лишь высказал мнение.
Свой компонент намного лучше. И MIGX не во всех случаях подходит для решения подобных задач.
Вообще по моему мнению модыксу не хватает одного важного дополнения — мастера быстрого написания компонентов, без глубоких знаний программирования, для решения несложных задач подобного типа. Рано или поздно такой мастер думаю будет написан.
MIGX — попытка сделать что-то похожее в рамках работы с конкретного ресурса. Но у него есть множество минусов, к примеру данные вносимые в MIGX не будут участвовать в поиске, или будут видны в виде json. Да и сложен он для неопытного пользователя.
Свой компонент намного лучше. И MIGX не во всех случаях подходит для решения подобных задач.
Вообще по моему мнению модыксу не хватает одного важного дополнения — мастера быстрого написания компонентов, без глубоких знаний программирования, для решения несложных задач подобного типа. Рано или поздно такой мастер думаю будет написан.
MIGX — попытка сделать что-то похожее в рамках работы с конкретного ресурса. Но у него есть множество минусов, к примеру данные вносимые в MIGX не будут участвовать в поиске, или будут видны в виде json. Да и сложен он для неопытного пользователя.
Вообще по моему мнению модыксу не хватает одного важного дополнения — мастера быстрого написания компонентов, без глубоких знаний программированияТакого не бывает.
Или ты знаешь термех, сопромат и строишь серьезные здания, или у тебя кубики лего и ты играешь в песочнице.
MIGX очень многое позволяет, потому и популярен. Я не принижаю его возможности, но лично мне он не нравится. Пару раз пытался использовать — в итоге перематерился и написал свое.
В общем: больше решений, хороших и разных!
Такого не бывает.
Или ты знаешь термех, сопромат и строишь серьезные здания, или у тебя кубики лего и ты играешь в песочнице.
Почему же не бывает, сделать можно все :) И модыкс — по большей части и есть те кубики лего, Большинство тривиальных задач в нем можно решить стандартными дополнениями именно методом складывания кубиков. А профи твоего уровня может писать нестандартные дополнения для решения нетривиальных задач.Я себе представляю это примерно так:
1) описание и создание таблицы в бд
2) выбор для каждого поля в бд типа ввода в форме (по типу тех же tv)
3) выбор метода вывода в менеджере, отдельным компонентом или новым типом ресурса
4) создание схемы и классов добавления, редактирования, удаления
5) запаковывание это все в пакет и установка
А выводить это все во фронтэнде можно твоим pdoTools.
Я бы такой компонент купил бы минимум на несколько сайтов. :)
Ты сейчас описал modExtra, в целом.
Берешь заготовку, пишешь модель, добавляешь сниппеты, страницу в админке и упаковываешь.
Я так все свои компоненты и делаю, обновляя этот modExtra, когда нужно.
Все дальнейшие упрощения — суть ограничения. Это когда тебе вместо песка и цемента дают готовые ж\б конструкции. Хочешь сарай, гараж, или будку для собаки — херачь это блоками 2х1.5 из бетона.
Я все-таки за песок+цемент и вдумчивое перемешивание с водой.
Берешь заготовку, пишешь модель, добавляешь сниппеты, страницу в админке и упаковываешь.
Я так все свои компоненты и делаю, обновляя этот modExtra, когда нужно.
Все дальнейшие упрощения — суть ограничения. Это когда тебе вместо песка и цемента дают готовые ж\б конструкции. Хочешь сарай, гараж, или будку для собаки — херачь это блоками 2х1.5 из бетона.
Я все-таки за песок+цемент и вдумчивое перемешивание с водой.
Василий подскажи, как с ресурсу привязать доп вкладку со своим компонентом?
Создавал новый тип страниц или через плагин при открытие документа привязываешь свой компонент, расскажи если не трудно.
Создавал новый тип страниц или через плагин при открытие документа привязываешь свой компонент, расскажи если не трудно.
Почитай о minishop2.
Приветствую!
Нужен точно такой же функционал. Можно ли купить этот компонент?
Нужен точно такой же функционал. Можно ли купить этот компонент?
Нет, он сделан под конкретного заказчика и не готов для продажи.
Код не универсален, документации нет, поддержки тоже.
Код не универсален, документации нет, поддержки тоже.
Скажите пожалуйста, как передать tv параметры в сниппет?
Делаю так:
,'includeTVs' => 'trener'
поля все заполнены, но все равно не выводит tv :(
Делаю так:
[[pdoSchedule?
&start=`7`
&tpl=`row_group2`
&tplEmpty=`@INLINE `
&tplRow=`@INLINE [[+days]]`
&includeTVs=`trener`
]]
И в сниппете раскоментировал и подправил синтаксис в этой строке: // Можно указать и выборку ТВ параметров, если нужно:,'includeTVs' => 'trener'
поля все заполнены, но все равно не выводит tv :(
У меня там опечатки были — поправил, теперь должно работать.
Я что то не так понял все таки, делаю так:
В сниппете TV вызываю так (как в pdoResources):
В сниппете TV вызываю так (как в pdoResources):
[[pdoSchedule?
&start=`7`
&tpl=`row_group2`
&tplEmpty=`@INLINE <td> </td>`
&tplRow=`@INLINE <tr>[[+days]]</tr>`
&includeTVs=`trener`
]]
В чанке row_group2 вывожу так:<span class="tibLine">[[+tv.trener]]</span>
В сниппете так:,'includeTVs' => !empty($includeTVs) ? $includeTVs : 'trener'
И все равно не выводит текст сниппета. Что не так делаю?
А tv. откуда возьмется? Ты видишь его где-то в сниппете?
Я не вижу, а значит выводить нужно
Или указать в сниппете еще и tvPrefix:
Я не вижу, а значит выводить нужно
[[+trener]]
Или указать в сниппете еще и tvPrefix:
,'includeTVs' => !empty($includeTVs) ? $includeTVs : ''
,'tvPrefix' => 'tv.'
Спасибо большое Василий, реально нужная и полезная вещь, давно гуглил нигде нет ничего внятного по созданию расписаний удобных для MODX, даже среди платных приложений, надеюсь многим начинающим, или простым людям которые не разбираются в программировании в силу отсутствия такого мышления :) я художник :) рисую, а вот писать сложно понять и разобраться, мозг не заточен под программирование, в общем спасибо большое, реально быстрее шуршит теперь страничка с расписанием, а то было 8 вызовов хоть и pdoResources но все равно самая тормозная страница на сайте была :)) Спасибо.
На здоровье!
Подскажите, а как сделать расписание «вертикального типа», вот как здесь никак не могу разобраться в этом вопросе.
Ничего кроме как 7-ми вызовов pdoResource (на каждый день недели) в голову не приходит :)
Пробую в простом php файле воспользоваться pdoFetch::getCollection(), но почему-то pdoFetch совсем не видит miniShop2
define('MODX_API_MODE', true);
require dirname(dirname(dirname(dirname(dirname(__FILE__))))) . '/index.php';
$pdo = $modx->getService('pdoFetch');
$parent = 140;
$allChild = $modx->getChildIds($parent,6,array('context'=>'web','class_key'=>'msCategory'));
$objects = $pdo->getCollection('msProduct', array('parent:IN'=>$allChild)); // Так не видит...
$objects = $pdo->getCollection('modResource', array('parent:IN'=>$allChild)); // Видит только так...
Сам MODX видит miniShop2: $objects = $modx->getCollection('msProduct', array('parent:IN'=>$allChild));
Василий не подскажешь, как заставить pdoFetch видеть минишоп?
Обновился и все работает!
Только вот msProductData все равно не видит…
Я так понимаю что сортировкой по TV этот замечательный компонент не оснащен, а что если нужно выводить расписание с фильтрами например вывести Все, Групповые, Водные и тп
Берешь, и дописываешь ручками.
ну это понятно, не понятно как куда чего =)
не могли бы вы помочь с сортировкой, или подсказать в какую сторону копать?
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.