Фильтрация по 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('&quot;', '"', $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('&quot;', '"', $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('"', '&quot;', $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
9
845
+7

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

Волков Николай
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
10 апреля 2018, 13:40
0
Скажите, а это код плагина или куда его нужно вставлять?
    Дмитрий
    10 апреля 2018, 13:42
    +1
    Это кастомный класс фильтра, который нужно положить в определенное место и подключить в настройках.