Ограничение выборки для inner join

Столкнулся с такой проблемой )
Есть ресурс «Галереи» и у него есть дочерние ресурсы, содержащие собственно галереи (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? Помогите пожалуйста, кто знает )
Саша Туманов
14 июля 2016, 08:59
modx.pro
2 904
0

Комментарии: 9

Саша Туманов
14 июля 2016, 15:07
0
Хотя бы думать в какую сторону, подскажите? )
    Владимир Кисилица
    14 июля 2016, 15:45
    0
    Можешь скрин таблицы msResourceFile скинуть с данными? Одной страницы достаточно будет. Подумаю как построить запрос
      Саша Туманов
      14 июля 2016, 17:55
      0
      Вот скрин таблицы с картинками:



      Вот полный код сниппета:

      /* Возвращает галереи 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, вроде как можно использовать подзапросы. Но собрать это в кучу, пока не хватает мозгов (
        but1head
        14 июля 2016, 18:14
        +2
        Простой 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
          Владимир Кисилица
          14 июля 2016, 19:22
          +1
          Я думал добавить условие для rank, но так не получится, везде значения этого поля равны 0. Тут нужно использовать подзапросы или реализовать разбор данных на уровне PHP. Используй пример, который предложил @but1head
            Саша Туманов
            14 июля 2016, 19:45
            0
            Спасибо большое, парни!
              Саша Туманов
              15 июля 2016, 15:24
              0
              Похоже, ограничение выборки для 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);
              }
          Максим
          15 июля 2016, 17:07
          +1
          Вот запрос, которым можно выбрать максимум 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
            Илья Уткин
            15 июля 2016, 17:25
            +2
            Ага, а через полгода ты сам не вспомнишь, что он делает)
            Уж лучше в чанке сниппет ms2gallery вызвать
            Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
            9