Фильтрация по MIGX таблице средствами mFilter2
Делаю проект, где нужно хитро задавать цвет у товаров, решение Володи msOptionsColorв рамках проекта показалось громоздким и немного не подходящим по другим причинам, поэтому решено было оформить все в MIGX и написать свои методы фильтрации. Я такое делал впервые.
Получилось следующее:
Вызывать так:
Получилось следующее:
<?php
class migxFilter extends mse2FiltersHandler {
public function getMigxsValues(array $tvs, array $ids) {
$filters = array();
$q = $this->modx->newQuery('modResource', array('modResource.id:IN' => $ids));
$q->leftJoin('modTemplateVarTemplate', 'TemplateVarTemplate', 'TemplateVarTemplate.tmplvarid IN (SELECT id FROM ' . $this->modx->getTableName('modTemplateVar') . ' WHERE name IN ("' . implode('","', $tvs) . '") )
AND modResource.template = TemplateVarTemplate.templateid'
);
$q->leftJoin('modTemplateVar', 'TemplateVar', 'TemplateVarTemplate.tmplvarid = TemplateVar.id');
$q->leftJoin('modTemplateVarResource', 'TemplateVarResource', 'TemplateVarResource.tmplvarid = TemplateVar.id AND TemplateVarResource.contentid = modResource.id');
$q->select('TemplateVar.name, TemplateVarResource.contentid as id, TemplateVarResource.value, TemplateVar.type, TemplateVar.default_text');
$tstart = microtime(true);
if ($q->prepare() && $q->stmt->execute()) {
$this->modx->queryTime += microtime(true) - $tstart;
$this->modx->executedQueries++;
while ($row = $q->stmt->fetch(PDO::FETCH_ASSOC)) {
if ($row) {
$migxs = (array) json_decode($row['value']);
foreach ($migxs as $migx) {
$v = $migx->title;
$name = strtolower($row['name']);
if (isset($filters[$name][$v])) {
$filters[$name][$v][$row['id']] = $row['id'];
} else {
$filters[$name][$v] = array($row['id'] => $row['id']);
}
}
}
}
} else {
$this->modx->log(modX::LOG_LEVEL_ERROR, "[mSearch2] Error on get filter params.\nQuery: " . $q->toSQL() . "\nResponse: " . print_r($q->stmt->errorInfo(), 1));
}
return $filters;
}
public function buildMigxFilter(array $values, $name = '') {
$keys = array_keys($values);
if (empty($keys) || (count($keys) < 2 && empty($this->config['showEmptyFilters']))) {
return array();
}
$results = $names = array();
$q = $this->modx->newQuery('modTemplateVar', array('name' => $name));
$q->select('elements');
$tstart = microtime(true);
if ($q->prepare() && $q->stmt->execute()) {
$this->modx->queryTime += microtime(true) - $tstart;
$this->modx->executedQueries++;
$tmp = $q->stmt->fetchColumn();
$names = array();
}
foreach ($values as $value => $ids) {
if ($value !== '') {
$migxs = json_decode(str_replace('"', '"', $value));
foreach ($migxs as $migx) {
$title = trim($migx->title);
if (!is_array($results[$title]['resources'])) {
$results[$title]['resources'] = array();
}
$results[$title] = array(
'title' => $title,
'value' => $migx->value,
'type' => 'tv',
'resources' => array_merge($results[$title]['resources'], $ids)
);
}
}
}
return $this->sortFilters($results, 'tv', array('name' => $name));
}
public function filterMigx(array $requested, array $values, array $ids) {
$matched = array();
$tmp = array_flip($ids);
$filteredValues = [];
foreach ($values as $value => $ids) {
$migxs = json_decode(str_replace('"', '"', $value));
foreach ($migxs as $migx) {
$title = trim($migx->value);
if (!is_array($filteredValues[$title])) {
$filteredValues[$title] = array();
}
$filteredValues[$title] = array_merge($filteredValues[$title], $ids);
}
}
foreach ($requested as $value) {
$value = str_replace('"', '"', $value);
if (isset($filteredValues[$value])) {
$resources = $filteredValues[$value];
foreach ($resources as $id) {
if (isset($tmp[$id])) {
$matched[] = $id;
}
}
}
}
return $matched;
}
}
Код, возможно, не самый торт, но вроде и не плохой. Единственное условие: у MIGX таблички должны быть объявлены два поля — title и value. Title выводится как заголовок фильтра, а value собственно отображается в адресной строке как параметр поиска. Вызывать так:
'filters' => 'ms|price:number,msoption|size,msoption|color,tv|color:migx',
Комментарии по коду приветствуются.
Поблагодарить автора
Отправить деньги
Комментарии: 13
Как по мне проще работать с нормальной таблицей в бд и использовать migxdb.
И что за ерунда:
$value = str_replace('"', '"', $value) ;
удален
Скажите, а это код плагина или куда его нужно вставлять?
Это кастомный класс фильтра, который нужно положить в определенное место и подключить в настройках.
Эх, как бы это переделать, чтобы выводить в стиле number?
Уже битый час вожусь — никак не получается. В migx-tv есть поле числовое. Подскажите пожалуйста, куда копнуть, чтобы вывести именно в виде number (чтобы было min и max значение).
Правильно ли я понимаю, что мне требуется только переписать buildMigxFilter и filterMigx?
Уже битый час вожусь — никак не получается. В migx-tv есть поле числовое. Подскажите пожалуйста, куда копнуть, чтобы вывести именно в виде number (чтобы было min и max значение).
Правильно ли я понимаю, что мне требуется только переписать buildMigxFilter и filterMigx?
Надо посмотреть, в каком формате возвращаются числовые значения и подогнать вывод этот формат. А затем сменить шаблон на подходящий. Точно сказать не могу, но если терпит, то завтра посмотрю и отвечу
спасибо, спустя 5 часов возни все таки получилось)
Вы, кстати, можете поделиться своим опытом здесь же! Поверьте, это многим поможет
Спасибо за опыт. Не хватает визуализации, как все это выглядит, ради чего делалось.
Прошло почти 3 года с момента написания заметки, визуализации не осталось.
Но если коротко — то для вывода цвета в HEX-формате. То есть был фильтр цвет, где текстом (поле title) было название цвета, а value был HEX-код цвета, который выводился в CSS для стилизации.
Типа того
Но если коротко — то для вывода цвета в HEX-формате. То есть был фильтр цвет, где текстом (поле title) было название цвета, а value был HEX-код цвета, который выводился в CSS для стилизации.
Типа того

Спасибо, не обратил внимание на дату создания поста. Смотрю обсуждается, подумал, что-то свеженькое. =) Но решение и сейчас применяется.
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.