Ограничение выборки для inner join
Столкнулся с такой проблемой )
Есть ресурс «Галереи» и у него есть дочерние ресурсы, содержащие собственно галереи (ms2gallery). Надо на страничке «Галереи», сделать предварительный просмотр вложенных галерей с переходом к полному просмотру. Причем в предварительном просмотре, должен быть заголовок, короткое описание взятое из контента самих галерей и 6 штук превьюшек.
Пытался сделать это при помощи сниппета ms2GalleryResources, но не сообразил как, поэтому решил делать напрямую:
И все бы хорошо, но не получается ограничить количество приджойненных превьюшек для каждого ресурса. Выбираются все. А попытка установить
приводит к тому, что ограничивается общее количество выбираемых превьюшек. Решается ли это вообще, средствами xpdo? Помогите пожалуйста, кто знает )
Есть ресурс «Галереи» и у него есть дочерние ресурсы, содержащие собственно галереи (ms2gallery). Надо на страничке «Галереи», сделать предварительный просмотр вложенных галерей с переходом к полному просмотру. Причем в предварительном просмотре, должен быть заголовок, короткое описание взятое из контента самих галерей и 6 штук превьюшек.
Пытался сделать это при помощи сниппета ms2GalleryResources, но не сообразил как, поэтому решил делать напрямую:
$modx->addPackage('ms2gallery', MODX_CORE_PATH . 'components/ms2gallery/model/');
$thumb = $modx->getOption('thumb', $scriptProperties, '120x90');
$q = $modx->newQuery('modResource', array(
'parent' => $modx->resource->id
));
$q->innerJoin('msResourceFile', 'files', "files.resource_id = modResource.id");
$q->sortby('files.resource_id', 'ASC');
$q->select('pagetitle,content,uri,files.resource_id,files.file,files.name,files.alt');
$q->where(array(
'published' => 1,
'files.type' => 'image',
'files.path:LIKE' => "%/{$thumb}%",
'files.active' => 1
)
);
И все бы хорошо, но не получается ограничить количество приджойненных превьюшек для каждого ресурса. Выбираются все. А попытка установить
$q->limit($limit);
приводит к тому, что ограничивается общее количество выбираемых превьюшек. Решается ли это вообще, средствами xpdo? Помогите пожалуйста, кто знает )
Комментарии: 9
Хотя бы думать в какую сторону, подскажите? )
Можешь скрин таблицы msResourceFile скинуть с данными? Одной страницы достаточно будет. Подумаю как построить запрос
Вот скрин таблицы с картинками:
Вот полный код сниппета:
В простом MySQL, это вроде как решается с помощью подзапроса. А в xpdo, вроде как можно использовать подзапросы. Но собрать это в кучу, пока не хватает мозгов (
Вот полный код сниппета:
/* Возвращает галереи ms2gallery дочерних, относительно текущего ресурса, ресурсов */
$modx->addPackage('ms2gallery', MODX_CORE_PATH . 'components/ms2gallery/model/');
$pdotools = $modx->getService('pdoTools');
$tplRow = $modx->getOption('tplRow', $scriptProperties);
$tplOuter = $modx->getOption('tplOuter', $scriptProperties);
$thumb = $modx->getOption('thumb', $scriptProperties, '120x90');
$fullsize = $modx->getOption('fullsize', $scriptProperties, '800x600');
$limit = $modx->getOption('limit', $scriptProperties, 16);
$imagesdir = '/assets/images/resources/';
$base = $modx->config['base_url'];
$res = array();
$rows = '';
$output = '';
$q = $modx->newQuery('modResource', array(
'parent' => $modx->resource->id
));
$q->innerJoin('msResourceFile', 'files', "files.resource_id = modResource.id");
$q->sortby('files.resource_id', 'ASC');
$q->limit($limit);
$q->select('pagetitle,content,uri,files.resource_id,files.file,files.name,files.alt');
$q->where(array(
'published' => 1,
'files.type' => 'image',
'files.path:LIKE' => "%/{$thumb}%",
'files.active' => 1
)
);
if($q->prepare() && $q->stmt->execute()) {
while ($row = $q->stmt->fetch(PDO::FETCH_ASSOC)) {
$res[$row['resource_id']][] = $row;
}
}
foreach($res as $gallery) {
foreach($gallery as $image) {
$smallsrc = $imagesdir.$image['resource_id']."/{$thumb}/".$image['file'];
$fullsrc = $imagesdir.$image['resource_id']."/{$fullsize}/".$image['file'];
$rows .= $pdotools->getChunk($tplRow, array(
'smallsrc' => $smallsrc,
'fullsrc' => $fullsrc,
'title' => $image['name'],
'alt' => $image['alt']
));
}
$output .= $pdotools->getChunk($tplOuter, array(
'rows' => $rows,
'pagetitle' => $gallery[0]['pagetitle'],
'content' => $gallery[0]['content']
));
unset($rows);
}
return $output;
//Вызов на странице "Галереи"
[[!getInnerGallery?
&thumb=`280x210`
&fullsize=`800x600`
&limit=`30`
&tplOuter=`@INLINE <div class='gallerypage bottom20'>
<h1 class="externalfont boldfont font150 bottom20">[[+pagetitle]]</h1>
<div class='clear left shadow outlinegreen lightgreenbg paperclip containingblock bottom20'>[[+content]]</div>
[[+rows]]<br class='clear'/>
</div>`
&tplRow=`@INLINE <a href='[[+fullsrc]]' class='cols col-3 col-4-m col-4-s modal textcenter'>
<img src='[[+smallsrc]]' title='[[+title]]' alt='[[+alt]]' />
</a>`
]]
В простом MySQL, это вроде как решается с помощью подзапроса. А в xpdo, вроде как можно использовать подзапросы. Но собрать это в кучу, пока не хватает мозгов (
Простой MySQL.
$sql = "SELECT * FROM {$modx->getTableName('modResource')} WHERE `id` > 0 LIMIT 1000";
$q = $modx->prepare($sql);
$q->execute();
$res = $q->fetchAll(PDO::FETCH_ASSOC);
foreach ($res as $v) {
//echo $v['pagetitle'];
}
Пара фокусов с xPDO
Я думал добавить условие для rank, но так не получится, везде значения этого поля равны 0. Тут нужно использовать подзапросы или реализовать разбор данных на уровне PHP. Используй пример, который предложил @but1head
Спасибо большое, парни!
Похоже, ограничение выборки для join, задача нетривиальная. С помощью подзапроса, можно ограничить выборку из левой таблицы, до присоединения правой. В моем случае, можно было бы сначала получить через modX::getChildIds, массив id дочерних документов, а потом делать по ним выборку с группировкой из таблицы msResourceFile. Но, опять же, ограничение выборки для каждой группы при GROUP BY, так же оказалось не очень простой задачей. Поэтому, решил не суетиться, а просто ограничить длину результирующего массива с картинками для каждого дочернего ресурса, благо — записей там немного.
$gallerylimit = $modx->getOption('gallerylimit', $scriptProperties, 8);
foreach($res as $gallery) {
foreach($gallery as $key => $image) {
if($key > $gallerylimit-1) break;
$smallsrc = $imagesdir.$image['resource_id']."/{$thumb}/".$image['file'];
$fullsrc = $imagesdir.$image['resource_id']."/{$fullsize}/".$image['file'];
$rows .= $pdotools->getChunk($tplRow, array(
'smallsrc' => $smallsrc,
'fullsrc' => $fullsrc,
'title' => $image['name'],
'alt' => $image['alt']
));
}
$output .= $pdotools->getChunk($tplOuter, array(
'rows' => $rows,
'pagetitle' => $gallery[0]['pagetitle'],
'content' => $gallery[0]['content']
));
unset($rows);
}
Вот запрос, которым можно выбрать максимум 3 первых картинки из каждой галереи:
SELECT `product_id`,`url` FROM (SELECT *, @rn := IF(@prev = `product_id`, @rn + 1, 1) AS rn, @prev := `product_id` FROM `modx_ms2_product_files` JOIN (SELECT @prev := NULL, @rn := 0) AS vars WHERE `parent`=0 ORDER BY `product_id` ASC, `rank` ASC) AS content WHERE rn <= 3
Ага, а через полгода ты сам не вспомнишь, что он делает)
Уж лучше в чанке сниппет ms2gallery вызвать
Уж лучше в чанке сниппет ms2gallery вызвать
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.