Задают много вопросов "а как выбрать бла-бла-бла и вывести все id товаров по нему?", на которые регулярно пишу в комментариях разные выборки на xPDO.
Пришло время собрать их в кучу, чтобы было проще искать.
Сниппет получает сумму всех товаров в категории, с учетом мультикатегорий MS2. Можно указать нужную категорию параметром $parent.
<?php
if (empty($parent)) {$parent = $modx->resource->id;}
$pids = array_merge(array($parent), $modx->getChildIds($parent));
$ids = array();
$q = $modx->newQuery('msProduct');
$q->where(array('class_key' => 'msProduct','parent:IN' => $pids,'published' => 1,'deleted' => 0));
$q->select('`msProduct`.`id`');
if ($q->prepare() && $q->stmt->execute()) {
$ids = $q->stmt->fetchAll(PDO::FETCH_COLUMN);
}
$q = $modx->newQuery('msProduct');
$q->leftJoin('msCategoryMember', 'Member', '`Member`.`product_id` = `msProduct`.`id`');
$q->where(array('class_key' => 'msProduct','Member.category_id:IN' => $pids,'published' => 1,'deleted' => 0));
$q->select('`msProduct`.`id`');
if ($q->prepare() && $q->stmt->execute()) {
$ids2 = $q->stmt->fetchAll(PDO::FETCH_COLUMN);
if (!empty($ids2)) {
$ids = array_unique(array_merge($ids, $ids2));
}
}
return count($ids);
Сниппет получает всех производителей, у которых есть хоть один активный товар и выводит в виде селектбокса.
<?php
$q = $modx->newQuery('msVendor');
$q->innerJoin('msProductData', 'msProductData', '`msProductData`.`vendor` = `msVendor`.`id`');
$q->innerJoin('msProduct', 'msProduct', array(
'`msProductData`.`id` = `msProduct`.`id`',
'msProduct.deleted' => 0,
'msProduct.published' => 1
));
$q->groupby('msVendor.id');
$q->sortby('name','ASC');
$q->select(array('msVendor.id', 'name'));
$options = '<option value="0">Нет</option>';
if ($q->prepare() && $q->stmt->execute()) {
while ($row = $q->stmt->fetch(PDO::FETCH_ASSOC)) {
$options .= '<option value="'.$row['id'].'">'.$row['name'].'</option>';
}
}
return '<select name="vendors">'.$options.'</select>';
Сниппет выбирает все значения указанной опции (теги, цвета) и печатает массив id товаров, у которых оно есть.
$key = 'tags'; // имя опции товара
$category = 0; // фильтрация по категории
$q = $modx->newQuery('msProductOption');
$q->innerJoin('msProduct', 'msProduct', 'msProduct.id=msProductOption.product_id');
$q->sortby('msProductOption.value','ASC');
$q->select('DISTINCT(msProductOption.value), msProduct.id');
$q->where(array('msProductOption.key' => $key));
if (!empty($category)) {
$ids = $modx->getChildIds($category);
$ids[] = $category;
$q->innerJoin('msCategory', 'msCategory', 'msCategory.id=msProduct.parent');
$q->where(array('msCategory.id:IN' => $ids));
}
$result = array();
if ($q->prepare() && $q->stmt->execute()) {
while ($row = $q->stmt->fetch(PDO::FETCH_ASSOC)) {
$result[$row['value']][] = $row['id'];
}
}
echo '<pre>';print_r($result); die;
Сниппет, который строит дерево ресурсов глубиной в 2 уровня, от указанного родителя.
$parent = 3;
$exclude_parents = array(100500,123456);
$template = 4;
$ids = $modx->getChildIds($parent));
$q = $modx->newQuery('modResource', array('parent:IN' => $ids, 'OR:id:IN' => $ids));
$q->andCondition(array('id:NOT IN' => $exclude_parents, 'template' => $template));
$q->select('id,pagetitle,parent');
$resources = array();
if ($q->prepare() && $q->stmt->execute()) {
while ($row = $q->stmt->fetch(PDO::FETCH_ASSOC)) {
if ($row['parent'] == $parent) {
if (isset($resources[$row['id']])) {
$resources[$row['id']] = array_merge($resources[$row['id']], $row);
}
else {
$resources[$row['id']] = $row;
$resources[$row['id']]['children'] = array();
}
}
else {
$resources[$row['parent']]['children'][$row['id']] = $row;
}
}
}
echo'<pre>';print_r($resources);die;
Сниппет выбирает и выводит все категории, к которым принадлежит товар - его можно использовать как своеобразные теги. Предложил Виктор Долгий.
<?php
if (empty($rid)) {$rid = $modx->resource->id;}
if (empty($pid)) {$pid = $modx->resource->parent;}
if (empty($delimeter)) {$delimeter = ' , ';}
$scheme = $modx->getOption('link_tag_scheme', null, 'full', true);
$q = $modx->newQuery('msCategory');
$q->leftJoin('msCategoryMember', 'msCategoryMember', array(
'`msCategory`.`id` = `msCategoryMember`.`category_id`'
));
$q->sortby('pagetitle','ASC');
$q->groupby('id');
$q->select(array('id','pagetitle'));
$q->where('`msCategoryMember`.`product_id` = '.$rid.' OR `id` = '.$pid);
$result = array();
if ($q->prepare() && $q->stmt->execute()) {
while ($row = $q->stmt->fetch(PDO::FETCH_ASSOC)) {
$url = $modx->makeUrl($row['id'], '', '', $scheme);
$result[] = '<a href="'.$url.'">'.$row['pagetitle'].'</a>';
}
}
return implode($delimeter, $result);
Указываете имя опции и родителя, откуда искать.
<?php
$key = 'tags'; // имя опции товара
$category = 0; // фильтрация по категории
$param1 = 'имя тега';
$q = $modx->newQuery('msProductOption');
$q->innerJoin('msProduct', 'msProduct', 'msProduct.id=msProductOption.product_id');
$q->where(array('msProductOption.key' => $key, 'msProductOption.value'=> $param1));
$q->sortby('msProductOption.value','ASC');
$q->select('DISTINCT(msProductOption.value), msProduct.id');
$q->where(array('msProductOption.key' => $key));
if (!empty($category)) {
$ids = $modx->getChildIds($category);
$ids[] = $category;
$q->innerJoin('msCategory', 'msCategory', 'msCategory.id=msProduct.parent');
$q->where(array('msCategory.id:IN' => $ids));
}
$result = array();
if ($q->prepare() && $q->stmt->execute()) {
while ($row = $q->stmt->fetch(PDO::FETCH_ASSOC)) {
$res['id'][] = $row['id'];
}
$result = implode(",", array_unique($res['id'])) ;
}
print_r($result);
Выборка дополнительных категорий и вывод ссылок на них.
<?php
if (empty($id)) {$id = $modx->resource->id;}
if (empty($tpl)) {$tpl = '@INLINE <a href="[[~[[+id]]]]">[[+pagetitle]]</a>';}
$pdo = $modx->getService('pdoFetch');
$conditions = array('product_id' => $id);
$options = array(
'innerJoin' => array(
'msCategory' => array('on' => 'msCategoryMember.category_id = msCategory.id')
),
'select' => array('msCategory' => 'all'),
'sortby' => 'msCategory.id'
);
$rows = $pdo->getCollection('msCategoryMember', $conditions, $options);
$output = '';
foreach ($rows as $row) {
$output .= $pdo->getChunk($tpl, $row);
}
return $output;
Нужна свежая версия pdoTools.
Если было еще - присылайте линки в комментах, будем дополнять.
Люблю ORM modx все просто и понятно, в действительности выходит что просто пишешь текс с пожеланиями что хочешь получить (:
Но почему без pdoTools?!
А зачем оно тут? Нет ни сложного построения запроса, ни дополнительных выборок, ни рендера чанков.
Это просто чистые выборки, которые можно интегрировать куда угодно, в том числе и в pdoTools-сниппет.
Не выводит цвета вторая выборка. У меня поле цвет лежит в таблице modx_ms2_products (преобразованное в строку), в параметрах сделал так:
$key = 'color'; // имя опции товара $category = $modx->resource->get('id'); // фильтрация по категории
в результате
Array ( )
но цвета есть. Если не задавать категорию - то все работает, все цвета возвращает. А если задать - то нет.
Написал оч простой код для получения уникальных цветов в категории товаров:
<?php $children_ids = implode(',', $modx->getChildIds($modx->resource->get('id'))); $q = $modx->query('SELECT DISTINCT(color) FROM modx_ms2_products WHERE id in('.$children_ids.')'); if (is_object($q)) { $result = array(); while ($row = $q->fetch(PDO::FETCH_ASSOC)) { $result[] = $row['color']; } print_r($result); }
Естественно.
Ты же изменил поле, и теперь оно хранит не массив (который копируется в таблицу опций), а строку. То, что ты получаешь без указания категории - это старые записи, скорее всего, уже не актуальные.
Так что да, тебе нужна простейшая выборка одного поля из одной таблицы, как ты и сделал.
А как в "Вывод производителей товаров MS2" выводить ссылку на товары этого производителя? Я немного под себя переделал ваш код и немного задумался а как добавить еще ссылку на продукцию по этому производителю? Тут у меня уже выводятся - id name logo и description (сниппет fabriki):
<?php $category = 0; // id категории для начала выборки $depth = 10; // глубина выборки по дочерним категориям $limit = 200; // ограничение результатов $q = $modx->newQuery('msProduct'); $q->innerJoin('msProductData', 'Data', 'msProduct.id = Data.id'); $q->innerJoin('msVendor', 'Vendor', 'Data.vendor = Vendor.id'); $q->leftJoin('msCategoryMember', 'Member', 'Member.product_id = msProduct.id'); $q->select('Vendor.id, Vendor.name, Vendor.logo, Vendor.description'); $q->groupby('Vendor.id'); $q->sortby('Vendor.name'); $q->limit($limit); $parents = $modx->getChildIds($category, $depth); $parents[] = $category; $q->where(array('msProduct.parent:IN' => $parents)); $q->orCondition(array('Member.category_id:IN' => $parents)); if ($q->prepare() && $q->stmt->execute()) { $res = $q->stmt->fetchAll(PDO::FETCH_ASSOC); foreach ($res as $elem) { echo '<div>'.$elem['id'].' - '.$elem['name'].' - '.$elem['logo'].' - '.$elem['description'].'</div>'; } }
вызываю его так [[!fabriki?]] на отдельной странице странице "Бренды" я понимаю, что нужно из msProduct брать ссылку наверное, но как не понимаю.. но могу и ошибаться
?
Я хочу вывести на страницу все товары одного производителя (для меню производителей). Как мне это сделать?
Все, сделал. Это оказалось легко - просто в getPage прописал &where=
{"vendor.id":1}
и все :)На локалке было все отлично, а вот на хосте выдает такие ошибки, ругаясь на where: (ERROR @ /index.php) [pdoTools] Error 42S22: Unknown column 'vendor.id' in 'where clause'
Вызов:
Если getResources, то ошибка такая:
(ERROR @ /index.php) Error 42S22 executing statement: Array ( [0] => 42S22 [1] => 1054 [2] => Unknown column 'vendor.id' in 'where clause' )
Подскажите из-за чего могут быть проблемы?
Vendor должен быть с большой буквы.
Спасибо, все заработало.
Ребята, что я делаю не так? Речь идет о выводе всех категорий и мультикатегорий, к которым принадлежит товар.
Создал сниппет, скопировал туда этот код.
Вызываю его [[$название_сниппета]] в чанке, чанк в шаблоне.
Пусто…
Всё, протупил. Вместо $ нужно !
НО Есть еще вопрос. Как выводить категории, глубиной в 0?
Т.е. сейчас мне сниппет выводит категорию и подкатегорию, в которой он лежит. А мне нужно, чтобы выводились только категории.
Спасибо!
Никто не подскажет?
Сам подумай.
Наверное, нужно выбрать тех, у кого parent = 0?
Это я прекрасно понимаю, только я не знаю что именно нужно изменить в коде сниппета=) Подскажите пожалуйста строчку.
Хм... Если мы выберем только тех, у кого parent=0, мне отобразится только непосредственно сами категории.
У меня структура такая:
Дак вот на странице товара (Диск R20 (1432)) мне нужно вывести список категорий, в которых он лежит, таких как "Panamera (213)". Конкретно только этого уровня. Категорий и мультикатегорий.
Понадобилось выводить все категории товара с возможностью показа родителей этих категорий. Может кому-нибудь тоже пригодится. Например если мы имеем вот такое дерево:
Например наш товар относится к категориям: Крутойбренд, Береза, Ель, Алюминий, Пластик. Кроме того, что товар уже стандартными функциями MS2 мы увидим в нужных нам категориях, мы также можем убить второго зайца создав из этих категорий характеристики товара, которые отобразятся на его странице в виде:
Характеристики: Бренд - крутойбренд Материал - береза, ель Отделка - алюминий, пластик
Вот дописанный код сниппета который это реализует:
<?php $startid = "23"; if (empty($rid)) {$rid = $modx->resource->id;} if (empty($pid)) {$pid = $modx->resource->parent;} if (empty($delimeter)) {$delimeter = ', ';} $scheme = $modx->getOption('link_tag_scheme', null, 'full', true); $q = $modx->newQuery('msCategory'); $q->leftJoin('msCategoryMember', 'msCategoryMember', array( '`msCategory`.`id` = `msCategoryMember`.`category_id`' )); $q->sortby('pagetitle','ASC'); $q->groupby('id'); $q->select(array('id','pagetitle')); $q->where('`msCategoryMember`.`product_id` = '.$rid.' OR `id` = '.$pid); $result = array(); if ($q->prepare() && $q->stmt->execute()) { while ($row = $q->stmt->fetch(PDO::FETCH_ASSOC)) { $result[] = $row['id']; } } $gparid = $modx-> getChildIds($startid, 1); foreach ($gparid as $parents) { $url = $modx->makeUrl($parents); $parid = $modx-> getChildIds($parents, 1); foreach ($parid as $dir) { if (in_array($dir, $result)) { $url = $modx->makeUrl($dir); $page = $modx->getObject('modResource', $dir); $pagetitle = $page->get('pagetitle'); $link[] = '<a href="'.$url.'">'.$pagetitle.'</a>'; } } if (!empty($link)) { $page = $modx->getObject('modResource', $parents); $gpagetitle = $page->get('pagetitle'); $gurl = $modx->makeUrl($parents); $dirs = implode($delimeter, $link); echo '<a href="'.$gurl.'">'.$gpagetitle.'</a> - '.$dirs.'</ br>'; unset($link); } }
Вероятно код слишком медленный, т.к. имеется вызов цикла внутри цикла и если категорий будет очень много будет тормозить... Но пока смог только так придумать. Если есть идеи как это быстрее реализовать очень хотелось бы их увидеть!
Подскажите как вывести дочерние категории на заданную глубину? Попробовал использовать приведенный тут сниппет "Дерево ресурсов" Но у меня
<?php $parent = 1; $depth = 1; // глубина выборки по дочерним категориям $template = 1; $exclude_parents = array(999); $ids = $modx->getChildIds($parent,$depth); // выборка ресурсов $q = $modx->newQuery('modResource', array('parent:IN' => $ids, 'OR:id:IN' => $ids)); $q->andCondition(array('id:NOT IN' => $exclude_parents, 'template' => $template)); //, 'isfolder=1' $q->select('id,pagetitle,parent'); $resources = array(); if ($q->prepare() && $q->stmt->execute()) { while ($row = $q->stmt->fetch(PDO::FETCH_ASSOC)) { if ($row['parent'] == $parent) { if (isset($resources[$row['id']])) { $resources[$row['id']] = array_merge($resources[$row['id']], $row); } else { $resources[$row['id']] = $row; $resources[$row['id']]['children'] = array(); } } else { $resources[$row['parent']]['children'][$row['id']] = $row; } } } echo'<pre>';print_r($resources);
выбирает на 2 уровня, вместо 1го.
Цель сделать боковое меню с подкатегориями
if ($q->prepare() && $q->stmt->execute()) { while ($row = $q->stmt->fetch(PDO::FETCH_ASSOC)) { if ($row['parent'] == $parent) { if (isset($resources[$row['id']])) { $resources[$row['id']] = array_merge($resources[$row['id']], $row); } else { $resources[$row['id']] = $row; // $resources[$row['id']]['children'] = array(); } } else { // $resources[$row['parent']]['children'][$row['id']] = $row; } } }
Другая крайность :) Выборка только 1го уровня.