Фильтрация по 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',
Комментарии по коду приветствуются.
Дмитрий
22 февраля 2018, 11:14
modx.pro
11
3 884
+7
Поблагодарить автора Отправить деньги

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

Волков Николай
24 февраля 2018, 05:35
0
Как по мне проще работать с нормальной таблицей в бд и использовать migxdb.
    Волков Николай
    24 февраля 2018, 05:44
    0
    И что за ерунда:
    $value = str_replace('"', '"', $value) ;
      Дмитрий
      24 февраля 2018, 11:44
      1
      0
      Да, извиняюсь, не заметил.
      Это редактор обработал теги. Изначально это выглядит так
      Aleksey
      25 февраля 2018, 11:56
      1
      0
      удален
        Sergey (Sentinel)
        10 апреля 2018, 13:40
        0
        Скажите, а это код плагина или куда его нужно вставлять?
          Дмитрий
          10 апреля 2018, 13:42
          +1
          Это кастомный класс фильтра, который нужно положить в определенное место и подключить в настройках.
          Lori
          13 октября 2021, 16:57
          0
          Эх, как бы это переделать, чтобы выводить в стиле number?
          Уже битый час вожусь — никак не получается. В migx-tv есть поле числовое. Подскажите пожалуйста, куда копнуть, чтобы вывести именно в виде number (чтобы было min и max значение).
          Правильно ли я понимаю, что мне требуется только переписать buildMigxFilter и filterMigx?
            Дмитрий
            13 октября 2021, 17:09
            0
            Надо посмотреть, в каком формате возвращаются числовые значения и подогнать вывод этот формат. А затем сменить шаблон на подходящий. Точно сказать не могу, но если терпит, то завтра посмотрю и отвечу
              Lori
              13 октября 2021, 23:31
              0
              спасибо, спустя 5 часов возни все таки получилось)
                Дмитрий
                13 октября 2021, 23:41
                +1
                Вы, кстати, можете поделиться своим опытом здесь же! Поверьте, это многим поможет
            Роман
            14 октября 2021, 09:12
            0
            Спасибо за опыт. Не хватает визуализации, как все это выглядит, ради чего делалось.
              Дмитрий
              14 октября 2021, 11:43
              0
              Прошло почти 3 года с момента написания заметки, визуализации не осталось.
              Но если коротко — то для вывода цвета в HEX-формате. То есть был фильтр цвет, где текстом (поле title) было название цвета, а value был HEX-код цвета, который выводился в CSS для стилизации.
              Типа того
                Роман
                14 октября 2021, 12:17
                +1
                Спасибо, не обратил внимание на дату создания поста. Смотрю обсуждается, подумал, что-то свеженькое. =) Но решение и сейчас применяется.
              Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
              13