Выборка ресурсов с TV-параметрами.
Здравствуйте.
Помогите пожалуйста дописать сниппет который будет выбирать ресурсы с TV-параметрами через newQuery.
Просмотрел много статей на сайте, есть с похожими проблемами, но так и не сумел на основе их разобраться со своей.
Вот что пока получается:
Понимаю, что это не совсем правильно, но не представляю как корректно нужно присоединить таблицу с TV.
Помогите пожалуйста дописать сниппет который будет выбирать ресурсы с TV-параметрами через newQuery.
Просмотрел много статей на сайте, есть с похожими проблемами, но так и не сумел на основе их разобраться со своей.
Вот что пока получается:
<?php
$parent = 7;
$resources = array();
$q = $modx->newQuery('modResource');
$q->leftJoin('modTemplateVarResource', 'modTemplateVarResource', 'modResource.id = modTemplateVarResource.contentid');
$q->where(array('modResource.parent' => $parent, 'modResource.published' => 1, 'modResource.deleted' => 0));
$q->select(array('modResource.*', 'modTemplateVarResource.*'));
if ($q->prepare() && $q->stmt->execute()) {
$resources = $q->stmt->fetchAll(PDO::FETCH_ASSOC);
}
echo '<pre>';
echo print_r($resources);
echo '</pre>';
Понимаю, что это не совсем правильно, но не представляю как корректно нужно присоединить таблицу с TV.
Комментарии: 3
Судя по количеству просмотров за 3 дня и отсутствию ответов, те кто прочитал пост либо не знали как помочь с проблемой, либо с мыслями вроде «еще один новичок с глупыми вопросами, который не может даже разобраться в документации» пролистывали дальше. И не удивительно — вопрос на самом деле кажется пустяковым, но вызвал у меня затруднение. И вот почему.
Задача такая: есть ресурсы с шаблоном «Семинар» и прикрепленными к ним несколькими TV. В частности TV с именем seminarDatestart, которая содержит дату начала семинара. Нужно выбрать все семинары, у которых дата начала старше текущей даты, т.е. семинары, которые еще не начались.
Все выглядит просто. Используем pdoResources для выборки:
Все выглядит корректно, но сниппет ничего не возвращает. Убираем строку &where=`{«seminarDatestart»:"[[NowTime]]"}` — возвращает все семинары, как и ожидается. Значит условие where не работает.
После долгих проб различных вариантов, решил заглянуть в базу данных. Оказалось, что значение seminarDatestart хранится в базе строкой вида 2015-02-20 23:31:00.
Что за бред?! Зачем вообще хранить в базе дату в виде отличном от timestamp — строку ни отсортировать, ни отфильтровать нормально не получится?! Если я в этом не прав, приведите примеры почему.
В общем, удивившись такой ситуации, понял, что нужно писать свой сниппет. Решил, что нужно получить массив семинаров со всеми TV-параметрами и уже из полученного массива исключить лишние. Вот только правильно приджоинить таблицы с TV у меня не получилось и я решил попросить помощи в этом топике.
Использовать getCollection изначально не хотелось, потому что функция возвращает коллекцию xPDOObjects, что, на мой взгляд дольше выполняется, чем получение чистого массива данных. Вот тут я могу оказаться не прав и с удовольствием выслушаю замечания.
Но даже и с getCollection решить проблему не получалось — не нашел ни одного примера выборки ресурсов со всеми TV-параметрами. Встречались примеры вроде этого, в котором выбираются ресурсы с одним определенным TV. Но на их основе ничего подходящего реализовать у меня не получилось.
Задачу решить не смог, решил передохнуть и подождать помощи в топике. А через три дня сел со свежей головой и сходу придумал альтернативный вариант решения, который в принципе меня удовлетворяет по простоте и скорости.
Выбираем все TV с id = 3 — это идентификатор seminarDatestart. Возвращается примерно следующий массив:
Далее в цикле смотрим: если значение TV больше текущего времени, то сохраняем id ресурса с этим TV, иначе — пропускаем. В результате мы получаем массив с идентификаторами нужных нам ресурсов. А дальше мы можем вызвать тот же pdoResources указав эти индентификаторы в параметре resources.
Задача решена. Получилось много букв, но надеюсь приведенный мной код кому-нибудь поможет.
Ну и, кроме всего прочего, вопрос топика то остается открытым — как, все таки, через newQuery получить список ресурсов со всеми TV-параметрами? Желательно без getCollections.
Задача такая: есть ресурсы с шаблоном «Семинар» и прикрепленными к ним несколькими TV. В частности TV с именем seminarDatestart, которая содержит дату начала семинара. Нужно выбрать все семинары, у которых дата начала старше текущей даты, т.е. семинары, которые еще не начались.
Все выглядит просто. Используем pdoResources для выборки:
[[pdoResources?
&parents=`7`
&tpl=`tpl.seminar`
&sortby=`seminarDatestart`
&sortdir=`ASC`
&depth=`3`
&limit=`0`
&hideContainers=`1`
&includeTVs=`seminarDatestart,seminarDateend,seminarCity`
&where=`{"seminarDatestart":"[[NowTime]]"}` // Сниппет NowTime возвращает текущее время в timestamp
]]
Все выглядит корректно, но сниппет ничего не возвращает. Убираем строку &where=`{«seminarDatestart»:"[[NowTime]]"}` — возвращает все семинары, как и ожидается. Значит условие where не работает.
После долгих проб различных вариантов, решил заглянуть в базу данных. Оказалось, что значение seminarDatestart хранится в базе строкой вида 2015-02-20 23:31:00.
Что за бред?! Зачем вообще хранить в базе дату в виде отличном от timestamp — строку ни отсортировать, ни отфильтровать нормально не получится?! Если я в этом не прав, приведите примеры почему.
В общем, удивившись такой ситуации, понял, что нужно писать свой сниппет. Решил, что нужно получить массив семинаров со всеми TV-параметрами и уже из полученного массива исключить лишние. Вот только правильно приджоинить таблицы с TV у меня не получилось и я решил попросить помощи в этом топике.
Использовать getCollection изначально не хотелось, потому что функция возвращает коллекцию xPDOObjects, что, на мой взгляд дольше выполняется, чем получение чистого массива данных. Вот тут я могу оказаться не прав и с удовольствием выслушаю замечания.
Но даже и с getCollection решить проблему не получалось — не нашел ни одного примера выборки ресурсов со всеми TV-параметрами. Встречались примеры вроде этого, в котором выбираются ресурсы с одним определенным TV. Но на их основе ничего подходящего реализовать у меня не получилось.
Задачу решить не смог, решил передохнуть и подождать помощи в топике. А через три дня сел со свежей головой и сходу придумал альтернативный вариант решения, который в принципе меня удовлетворяет по простоте и скорости.
<?php
$parent = 7;
$tmplvarid = 3; // id TV параметра seminarDatestart
$output = '';
$resourcesIds = array();
$nowTime = time();
$q = $modx->newQuery('modTemplateVarResource');
$q->where(array('modTemplateVarResource.tmplvarid' => $tmplvarid));
$q->select(array('modTemplateVarResource.*'));
if ($q->prepare() && $q->stmt->execute()) {
while ($row = $q->stmt->fetch(PDO::FETCH_ASSOC)) {
if (strtotime($row['value']) > $nowTime) {
$resourcesIds[] = $row['contentid'];
}
}
}
if (!empty($resourcesIds)) {
$output = $modx->runSnippet('pdoResources',
array(
'parents' => $parent
,'resources' => implode(',', $resourcesIds)
,'limit' => 0
,'tpl' => 'tpl.seminar'
,'sortby' => 'seminarDatestart'
,'sortdir' => 'ASC'
,'depth' => 3
,'hideContainers' => 1
,'includeTVs' => 'seminarDatestart,seminarDateend,seminarCity'
)
);
}
echo $output;
Выбираем все TV с id = 3 — это идентификатор seminarDatestart. Возвращается примерно следующий массив:
Array
(
[0] => Array
(
[id] => 5
[tmplvarid] => 3
[contentid] => 45
[value] => 2015-02-20 23:31:00
)
[1] => Array
(
[id] => 12
[tmplvarid] => 3
[contentid] => 46
[value] => 2015-03-11 09:12:00
)
)
Далее в цикле смотрим: если значение TV больше текущего времени, то сохраняем id ресурса с этим TV, иначе — пропускаем. В результате мы получаем массив с идентификаторами нужных нам ресурсов. А дальше мы можем вызвать тот же pdoResources указав эти индентификаторы в параметре resources.
Задача решена. Получилось много букв, но надеюсь приведенный мной код кому-нибудь поможет.
Ну и, кроме всего прочего, вопрос топика то остается открытым — как, все таки, через newQuery получить список ресурсов со всеми TV-параметрами? Желательно без getCollections.
Оказалось, что значение seminarDatestart хранится в базе строкой вида 2015-02-20 23:31:00.Это формат называется, как ни странно, datetime.
Что за бред?! Зачем вообще хранить в базе дату в виде отличном от timestamp — строку ни отсортировать, ни отфильтровать нормально не получится?! Если я в этом не прав, приведите примеры почему.
Он отлично сортируется и в начальном варианте твой сниппет NowTime должен был просто делать так:
<?php
return date('Y-m-d H:i:s', time());
Ну а в pdoResources его нужно вызывать вот так:
[[!pdoResources?
&parents=`7`
&tpl=`tpl.seminar`
&sortby=`seminarDatestart`
&sortdir=`ASC`
&depth=`3`
&limit=`0`
&hideContainers=`1`
&includeTVs=`seminarDatestart,seminarDateend,seminarCity`
&where=`{"seminarDatestart:>":"[[NowTime]]"}`
]]
Обрати внимание, что в условии seminarDatestart:>, то есть дата больше, а сам pdoResources должен быть некэшрованным, потому что текущее время непостоянно.Вот и всё, вопрос решен.
Свой велосипед, понятно, всегда приятнее и лучше, но уж что даты сортируются — нужно знать. В последней версии pdoTools даже появился параметр &sortbyTVType с вариантами decimal, integer, string и datetime.
Спасибо за дельные замечания. В результате остановился на таком варианте:
[[!pdoResources?
&parents=`7`
&tpl=`tpl.seminar`
&sortby=`seminarDatestart`
&sortdir=`ASC`
&depth=`3`
&limit=`0`
&hideContainers=`1`
&includeTVs=`seminarDatestart,seminarDateend,seminarCity`
&where=`{"seminarDatestart:>":"[[NowTime:date=`%Y-%m-%d %H:%M:%S`]]"}`
]]
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.