- Проверено Modstore
- Бесплатные будущие обновления
- Работа на тестовом и публичном домене
- 12 месяцев тех. поддержки


Возможности
- Фасетная фильтрация — фильтрация по любым полям ресурсов, TV, опциям MiniShop3
- SEO URL — человекочитаемые URL вида /catalog/brand_apple/color_black/
- Кросс-фильтрация — подсчёт доступных значений с учётом активных фильтров
- AJAX — обновление результатов без перезагрузки страницы
- Headless API — REST API для интеграции с Vue, React, Svelte
- SEO оптимизация — динамические title, description, H1, canonical
- Словоформы — склонение названий фильтров в SEO-текстах
- Интеграция — работает с MiniShop3, mSearch, pdoTools
- Vue-интерфейс — современная админ-панель на Vue 3 + PrimeVue
Системные требования
- MODX Revolution | 3.0.0+
- PHP | 8.1+
- MySQL | 5.7+ / MariaDB 10.3+
Зависимости
- pdoTools 3.x — для работы сниппетов и шаблонизатора Fenom
- VueTools — для административного интерфейса
- MiniShop3 (опционально) — для фильтрации товаров
Быстрый старт
Добро пожаловать в документацию — docs.modx.pro/components/mfilter/quick-start
История изменений mFilter
Журнал версий компонента mFilter для MODX 3.x. Свежее сверху.
1.4.2-beta1
Исправления
- mFilterForm: на пустом разделе форма больше не показывает значения из соседних категорий. Проверка
!empty($baseIds)в сниппете трактовала пустой массив как «scope не задан» → каждый FilterType шёл по parents/depth и тянул значения из родительских категорий. Теперь — fallback на свой расчёт scope через новыйFilter::getResourceIds(), и короткое замыкание на «нет значений» для пустого раздела. - mFilterNav: на пустом разделе сниппет больше не дампит весь
mfl_slugsдля запрошенногоfilterKey. Та же!empty([])ловушка — при пустых baseIds suggestions не получались,hideEmptyмолча пропускался, в вывод шли все исторические слаги. Добавлено различение трёх состояний baseIds:null/[]/ непустой. - mFilterSitemap: карта сайта больше не содержит «мёртвых» URL для значений фильтров без реальных товаров в разделе. Старая реализация генерировала декартово произведение всех слагов из
mfl_slugsбез проверки пересечения с реальными товарами — sitemap раздувался 404-страницами, бот тратил crawl budget впустую.
Рефакторинг
- mFilterNav теперь использует
FacetIndexReader::batchGetTextValues()для индексированных текстовых ключей — один SQL вытягивает (value, count) для всех ключей сразу. Slug-строки подгружаются черезpreloadForFilters(). Не-индексированные ключи остаются на legacy-пути. На странице с 2–3 индексированными ключами вместоN×getByFilter + 1×getSuggestionsForIdsтеперь1×batch SQL + 1×IN(...). - mFilterSitemap:
- Single-filter URLs: значения берутся из
FacetIndexReader::getTextValues()со scope отFilter::getResourceIds()— только реально существующие значения для раздела. - Two-filter URLs: новый метод
FacetIndexReader::getCombinedTextValues()делает self-JOIN индекса поproduct_id— возвращает только реально сосуществующие пары(value1, value2). Декартово произведение для пар ушло. - Пустые разделы пропускаются до перебора слагов — для них вообще не делается SQL.
- Cache key расширен
cultureKey,tplWrapper,sitemapSchema,forceXML,return,depth(несколько pre-existing пропусков исправлены заодно). - Новый опциональный параметр сниппета
depth(default10) для scope.
- Single-filter URLs: значения берутся из
Новый публичный API
Filter::getResourceIds(int $resourceId, int $depth = 10): int[]— возвращает все ID товаров раздела с тем же scope, что иFilter::apply()(parents/depth/published/deleted/msCategoryMember secondaries), но без фильтров и пагинации. Для пустого раздела возвращает[]. Используется в mFilterForm/mFilterNav/mFilterSitemap, когда mFilter-сниппета на странице нет.FacetIndexReader::getCombinedTextValues(string $key1, string $key2, ?array $productIds = null): array— пары значений двух фильтров, реально встречающиеся вместе у товаров. Один SQL self-JOIN поmfl_facet_index_text. Используется sitemap'ом, годится для любой аналитики «какие пары значений сосуществуют».FilterHandler::isEmptyScope(array $context): bool— guard для headless/API-вызовов, которые явно ставятfiltered_idsилиresource_idsв[]. Пропускает per-FilterType SQL и возвращает пустой envelope.FilterHandler::buildEmptyFiltersData()/buildEmptySuggestions()— внутренние хелперы, формирующие envelope с пустыми values, точно совпадающий по форме с реальнымиgetFiltersData()/getSuggestions().
Хардeнинг (по результатам ревью)
- Cache key в mFilterNav теперь содержит сигнатуру
$baseIds(count + crc32 от отсортированных ID). Без неё разные scope могли коллизить на одной записи кэша приcache=1. - mFilterNav: ранний выход на пустом scope пишет пустую строку в кэш — постоянно-пустые секции больше не дёргают
getResourceIds()на каждом запросе. - mFilterNav:
sort_orderсохранён для индексированного пути через map per-key (только когдаsortBy=sort_order). - mFilterNav: режим
showCount=0 hideEmpty=0сохранён — в нём весьfilterKeyListидёт по slug-driven пути без scope resolve. Историческая «SEO-облако-как-есть» семантика не тронута. - Все
$modx->log(1, ...)приведены кmodX::LOG_LEVEL_ERRORради единообразия с правилом проекта.
1.4.1-beta1
Новые возможности
Автосинхронизация индекса фасетов — закрывает известное ограничение из 1.4.0, ручная пересборка после редактирования товаров через MODX/MS3 больше не нужна. Три слоя покрывают типичные пути правок:
- Плагин на
OnDocFormSave/OnResourceDelete— инкрементально обновляет индекс для сохранённого/удалённого товара (5–20 мс на товар, незаметно для UX). Фильтр поclass_keyпропускает сохранения статических страниц при установленном MS3. - Плагин на
msOnAfterImport— запускает полную пересборку после CSV-импорта MS3 (через Scheduler если установлен, иначе синхронный fallback с предупреждением в логе). - Новая recurring Scheduler-задача
mfl_sync_facet_index(+5 минут) — догоняет вызовы$resource->save()без процессора и SQL-импорты, обновляющиеeditedon. Читаетlast_sync_atизMflCache, пересобирает батчами по 5000 ID, удаляет soft-deleted строки. На простаивающих сайтах ничего не делает, лог не засоряет.
Дополнительно:
- Новый метод
FacetIndexBuilder::syncByEditedon(?int $sinceTimestamp = null)— инкрементальная синхронизация. Используется новой Scheduler-задачей и доступен из своего кода. - Новый метод
FacetIndexBuilder::shouldIndexClassKey(?string $classKey)— хелпер гейтинга операций по товарам, ограничивает работуmsProduct'ами при установленном MS3. - Задача
rebuildFacetIndex.phpтеперь принимает параметрmode=full|sync— универсальный обработчик для on-demand вызовов.
Что по-прежнему требует ручной пересборки
- Прямой SQL
UPDATEбезeditedon=NOW()— sync такого не видит DELETE FROM modx_site_contentчерез сырой SQL — нетdeletedon-строки для детекции
Хардeнинг (по результатам ревью PR #13)
- Убран SELECT по
msProductData.editedon— такой колонки в MS3 нет, recurring task падал бы каждые 5 минут сUnknown column - Soft-delete теперь детектится по
deletedon(MODX 3 Delete-процессор не трогаетeditedon) - Baseline
last_sync_atсдвинут на −1 секунду, чтобы записи, закоммиченные в ту же секунду, что и наш SELECT, не терялись навсегда
1.4.0-beta1
Главное
Денормализованный индекс фасетов (mfl_facet_index_text / mfl_facet_index_num), заменяющий JOIN'ы к msProductData / msProductOption / modTemplateVarResource на лету. На каталоге 30k применение фильтра ускорилось с ~30с до ~1.7с, расчёт suggestion'ов — с сотен мс до единиц. Каталоги 200k+, ранее неюзабельные, теперь работают за секунды.
Новые возможности
- Прозрачное чтение — обработчики FilterType сами определяют индексированные ключи (
hasIndexedTextKey/hasIndexedNumKey) и переключаются между индексом и fallback'ом на исходные таблицы. Существующие конфиги наборов фильтров работают без изменений. - Бесшовная миграция — при upgrade резолвер ставит задачу
mfl_rebuild_facet_indexв очередь Scheduler. Пока пересборка не выполнилась — фильтрация продолжает работать через fallback, простоев нет. Без Scheduler — одна кнопка в админке. - Админка — новая вкладка «Обслуживание» со статусом индекса, количеством записей, временем последней пересборки, ручной пересборкой (напрямую или через Scheduler), управлением кэшем. Старый прогрев перенесён в сворачиваемый блок с пометкой Legacy.
- Кнопка «Переиндексация» в шапке — единая, заменяет несколько прежних. Подсвечивается жёлтым, пока индекс не построен.
- Инкрементальная пересборка при сохранении набора — пересобирается только изменённый ключ, а не весь каталог. Изменения определяются через рекурсивный
ksort+json_encode(порядок ключей не важен).
Производительность
- Batch SQL для текстовых suggestion'ов — при ≥2 индексированных текстовых фильтрах их значения собираются одним
GROUP BYвместо N отдельных сканов. ~4× быстрее на многофильтровых страницах. - *`COUNT()
вместоCOUNT(DISTINCT)`** в чтениях из индекса — безопасно благодаря уникальности PRIMARY KEY. Filter::applyToIdsиспользует raw PDO fetch вместоgetIterator()— экономит 2–3 секунды на выборках 30k+ строк.
Инфраструктура
- Новая Scheduler-задача
mfl_rebuild_facet_indexдля фоновой полной пересборки. - Builder обнуляет PHP-таймауты (
set_time_limit(0),ignore_user_abort(true)) на каждом фильтре; безопасен для пересборок через HTTP. - Новый эндпойнт
/maintenance/statusвозвращает блокfacet_indexс количеством строк, временем последней пересборки и флагом pending-run.
Хардeнинг (по результатам ревью)
- Количество строк после INSERT IGNORE читается из возвращаемого значения
PDO::exec()— убран лишнийSELECT ROW_COUNT(). - REGEXP для числовых значений принимает опциональный знак и запятую как десятичный разделитель;
REPLACEпередCASTне даёт'1,5'молча превратиться в 1. Мусор вида'1.2.3.4'отбраковывается. - Whitelist
^[a-zA-Z0-9_]+$для имени поля вFacetIndexBuilder— defense-in-depth, конфиг доступен только админам, но backticks не защищают от payload вида; DROP TABLE; --. - Ошибки PDO
prepare/executeвFilter::applyToIdsтеперь логируютerrorInfo+ SQL вместо тихого пустого результата. - WarmupTab во вкладке «Обслуживание» больше не монтируется при свёрнутом Panel — экономит запрос к
/warmup-configsпри каждом открытии вкладки.
Известные ограничения
OnDocFormSaveпока не пересобирает facet-индекс — индекс не обновляется автоматически при редактировании товара через админку. Закрыто в 1.4.1-beta1.- Удаление набора фильтров не чистит индекс — orphan-строки накапливаются до следующей полной пересборки. Косметика, на корректность не влияет.
- Race condition в
buildAll()при долгой пересборке (окно между TRUNCATE и INSERT) — отслеживается в issue #12. В типичных FPM-конфигурациях практически не проявляется.
1.3.3-beta1
Исправления
- URL Patterns:
parse_regexтеперь автогенерируется изurl_pattern, если пустой. Раньше для паттернаdvigatel--{value}нужно было вручную писать regex, иначе URL отдавал 404 при прямом переходе. Поддерживаются плейсхолдеры{key},{value},{values}. - Hide_key паттерны исключены из автогенерации — их
url_pattern(например{value}) дал бы слишком жадный/^(.+)$/, перехватывающий любой сегмент. Hide_key продолжают идти черезhasSlug()валидацию.
1.3.2-beta1
Новые возможности
- Canonical URL handling — фильтрованные URL без trailing slash теперь возвращают 404 по умолчанию (настраивается через
mfilter.non_canonical_url_handling:404 | 301 | off). Предотвращает SEO-дубли. - DOM-событие
mfilter:contentLoadedдиспатчится после обновления результатов сdetail: container, append, total, instance— для интеграции внешнего JS на новых карточках товаров.
Изменения
- Дефолт
mfilter.url_separatorизменён с_на--. На существующих установках значение сохраняется при upgrade ('settings' => falseв build config); затрагивает только новые установки.
1.3.1-beta1
Исправления
- loadMore: ошибка в user success callback больше не сбрасывает page counter (emit вынесен из try/catch)
- loadMore: boundary check предотвращает запросы за последнюю страницу
- loadMore: автоскрытие кнопки при загрузке всех элементов (через
data-mfilter-load-more) - Range sliders: десятичные значения отображаются корректно (17.6 больше не округляется до 18)
- Range sliders: автоопределение шага по диапазону (~100 шагов, «красивые» числа)
- Range sliders: кастомный шаг через
data-stepна slider-элементе - Range inputs:
step="any"в tpl снимает HTML5-блокировку submit с десятичными значениями - Range inputs: дефолтные (неизменённые) значения больше не попадают в URL при submit
syncFormWithState: range-фильтры не помечаются как user-changed, если совпадают с дефолтамиinitPaginationState: глобальный DOM-поиск wrapper'а, когда форма и результаты — отдельные элементы
Новые возможности
- Empty results state: элемент
.mfilter-emptyавто-показывается/скрывается поtotal(содержимое контролируется шаблоном)
1.3.0-beta1
Новые возможности
- Select-фильтры: option с count=0 получают атрибут
disabledчерез suggestions - Range-фильтры: десятичные числа в SEO URL (например,
price_99.50_500) - JS:
syncFormWithState()при инициализации — инпуты формы синхронизируются с URL-состоянием при загрузке страницы
Улучшения
- Удалён legacy JS-стек:
mfilter.core.js,mfilter.api.js,mfilter.ui.js(−2515 строк).FilterUI.js— единственная реализация UI. - Убран hardcoded whitelist
isRangeFilter()изSlugParserиUrlBuilder— любой URL-сегментkey_number_numberтеперь трактуется как range. - Regex
SlugParserподдерживает ключи с цифрами (price2,area3). - Дефолтная сортировка не попадает в URL (сравнение с конфиг-дефолтом, а не хардкодом
'menuindex'). - Точка входа
mfilter.js: убран MFilterCore fallback, только MFilterUI. - Резолвер
resolve.frontend_assets.php: автообновление системной настройки при upgrade, если сторонних файлов не обнаружено.
Исправления
- Range-инпуты без слайдера:
data-user-changedставится при ручном вводе, фикс игнорирования значений при submit - Утечка пагинации pdoPage:
pageNavVarсменён с пустой строки на неиспользуемый плейсхолдер (pdoPage трактовал''как дефолт) - JS
parseFilterPath: разделитель range берётся изurlSepвместо хардкода'_' - JS
resetFilterCounts:option.value !== ''вместо falsy-проверки (фикс option сvalue="0") - JS
syncFormWithState: корректная обработка range-инпутов (по name) и select-элементов
Ломающие изменения
window.MFilterCoreудалён — используйтеwindow.MFilterUIwindow.MFilterAPIудалён — функционал вcore/ApiClient.jsиcore/FilterAPI.js- Плейсхолдер
{$results}удалён из outer-чанка — используйте{$rows} - Legacy JS-файлы удалены — если шаблон вручную подключал
mfilter.core.js/mfilter.api.js/mfilter.ui.js, удалите эти` теги. Ассеты регистрируются автоматически через настройкуmfilter.frontend_assets`.
1.2.3-beta1
Улучшения
- JS API:
loadMore()теперь эмитит полный цикл событий (beforeSubmit,success,error,afterSubmit) с флагомappend: trueдля отличия от обычного submit - JS API:
instance.stateтеперь содержитpageCountиtotal, синхронизируются с ответом сервера после каждого запроса - JS API: SSR-инициализация
pageCount/totalиз атрибутовdata-page-countиdata-totalна wrapper-элементе - Дефолтный
tplOuter: добавленыdata-page-countиdata-totalдля SSR-инициализации состояния
Исправления
- Админка: дерево ресурсов в редакторе набора фильтров не авто-чекает родителя при выборе всех потомков (отключён PrimeVue propagateUp). Родитель чекается только прямым кликом
- Админка: снятие чекбокса с дочернего ресурса не меняет состояние родителя
- Админка: кнопка «Выбрать всех потомков» выбирает только потомков, не сам узел
Внимание: если используете кастомный
tplOuter, добавьте в wrapper-элементdata-page-count="{$pageCount}" data-total="{$total}"для SSR-инициализации пагинации. Без этих атрибутовpageCount/totalпоявятся только после первого AJAX-запроса.
1.2.2-beta1
Исправления
- Поддержка msCategoryMember: товары из вторичных MS3-категорий теперь учитываются в counts фильтров, пагинации и листинге товаров
- Централизованы хелперы родительской фильтрации в
AbstractFilterType(buildParentSqlCondition,getProductIdsByParents) - Исправлена OR-группировка в xPDO-запросах — unpublished/deleted товары не утекают через вторичные категории
- In-memory кэш для
getSecondaryProductIds()— нет повторных DB-запросов в одном request'е - Удалены дубли
getProductIdsByParents()из VendorsFilterType, BooleanFilterType, NumberFilterType - TvIndexer: индексация TV покрывает товары из вторичных категорий
1.2.1-beta1
Улучшения
- Задача
mfl_warmupстала рекуррентной (каждые 50 минут) — кэш с дефолтным TTL 3600с никогда не протухает - Удалён legacy
warm_suggestionsчерез HTTP-запросы изrebuildCache(заменён наmfl_warmup)
Code review fixes
autoCreateConfig: in-memory guard предотвращает повторные DB-запросы на cache miss в одном request'еwarmConfig:try/finallyгарантирует восстановление$modx->resourceпри exceptionwarmConfig:depthберётся из параметров конфига, а не из хардкодаWarmupManager: все timestamps черезgmdate()(UTC consistency)SnippetCallParser: добавлены скобки для читаемости, документированы ограниченияparsePhpArrayWarmupConfigController: whitelistsortByдля предотвращения SQL-инъекций
1.2.0-beta1
Новые возможности
- Подсистема warmup: настраиваемый прогрев кэша baseIds и фасетных counts
- Админка: новая вкладка «Прогрев» для управления конфигурациями
- Парсер вызова сниппета: поддержка Fenom, MODX-тегов и JSON для извлечения параметров
- Автосоздание конфигов при первом посещении страницы (cache miss)
- Scheduler-задача
mfl_warmup: фоновый прогрев через cron - Кнопка «Запустить через Scheduler» в админке для фонового выполнения
Модели
- Новая таблица
mfl_warmup_configs: конфигурации сelement,params,cache_key_hash - Новая таблица
mfl_warmup_config_resources: many-to-many привязка конфигов к страницам
Интеграция
- Сниппет mFilter проверяет warmup-кэш перед вызовом
ElementRunner::getIds() WarmupKeyBuilder: детерминистский MD5-хеш только от параметров, влияющих на выборку (дефолты исключаются)WarmupManager: CRUD, чтение/запись кэша, выполнение прогрева, авто-создание на cache miss- API: 10 эндпойнтов для управления конфигами (
/warmup-configs/*)
Улучшения
Filter::getSuggestionsForIds()кэширует результаты вMflCache(включает прогрев фасетных counts)- Warmup также прогревает значения фильтров (
getFilters) дляmFilterForm— устраняет 13–19с холодного старта - Отдельная Scheduler-задача
mfl_warmup(раньше переиспользоваласьmfl_rebuild_cacheс путаными параметрами) - Cache expiration через UTC (
gmdate) — фикс преждевременной инвалидации при разных timezone у cron и web TvIndexer::indexResource()индексирует только TV, используемые в фильтрах, а не все TV ресурса
Исправления
- Удалено отладочное логирование из
ColorsFilterType
1.1.5-beta1
Улучшения
- Cache invalidation: кэш значений фильтров (MflCache) теперь автоматически очищается при изменении конфигурации набора
Исправления
- Suggestion counts для Vendors и Boolean типов показывали завышенные числа после AJAX-фильтрации (отсутствовал scope-limit
resource_ids) - Имя вендора отображалось как заголовок ресурса в выбранных фильтрах и крошках (
vendor_idрезолвился как ID ресурса MODX, а не как ID вендора MS3) - Сортировка в lazy-loading таблицах админки (Slugs, WordForms)
1.1.4-beta1
Улучшения
- SSR-профилировщик: debug-панель показывает метрики производительности на первой загрузке страницы (не только после AJAX)
Исправления
- Падение при удалении пакета: класс
EncryptedVehicleне находился, так как MODX удаляет namespace-директории до обработки vehicle. Резолвер делает fallback на загрузку из директории распакованного пакета - Удаление пакета блокировалось расшифровкой:
EncryptedVehicle::uninstall()больше не падает при отсутствии ключа, идёт по cleanup через резолвер - Ошибка «Could not load class MflPageConfig» при установке (модель удалена в 1.1.0, но миграционный резолвер на неё ссылался)
- Warning «Constant COMPONENT_NAME already defined» при установке
1.1.3-beta1
Исправления
- Дублирование SQL JOIN к
msProductDataвFilter::apply(): NumberFilterType добавлялinnerJoin('Data'), потомapply()добавлялleftJoin('Data')→ MySQL «Not unique table/alias» и пустые результаты для slider-фильтров - Конфликт алиасов TV-фильтров: DefaultFilterType, DateFilterType, MonthFilterType, YearFilterType, DayFilterType использовали фиксированный алиас
'TVR'для TV-JOIN'ов — два TV-фильтра одновременно ломали SQL. Теперь уникальные алиасыTVR_{field} - Пустой hash в
mfilter.outer.tpl: Fenom{var}присваивание с?:и$_pls[]молча возвращает пустоту. Замена на прямой вывод{$_pls['hash']}
1.1.2-beta1
Исправления
- SQL-ошибка в
Filter::apply(): колонкиData.vendorнет вmsProductData, заменено наData.vendor_id MsProductSource::getKnownFields():vendor→vendor_idпод актуальную схему MS3- Детектор полей
SourceHandler:vendor→vendor_id - Удалён дубль
vendorиз полей сортировки (уже естьvendor_id)
1.1.1-beta1
Исправления
- API:
getFilterSetService()→getFilterSetManager()вFilterController - API:
getFilterTypeRegistry()→getFilterTypesRegistry()вFilterController FilterControllerобрабатывал FilterSet-массив как xPDO-объект ($filterSet->get()→$filterSet[])- Задача
rebuildCache: неверный формат аргумента дляFilter::getFilters()(массив вместо int) - Задача
rebuildCache: использование void-результатаrebuildRouterCache()как массива - Удалён dead-код в
BooleanFilterType::getValueCounts() - Очищен PHPStan baseline: удалены 6 устаревших записей для удалённых файлов/методов
1.1.0-beta
Новые возможности
- mFilterCrumbs: сниппет хлебных крошек с фильтр-сегментами и SEO-разметкой (Schema.org, JSON-LD)
- mFilterSelected: компонент отображения выбранных фильтров
- mFilterSitemap: сниппет и Scheduler-задача для генерации sitemap
- mFilterNav: SEO-навигация по фильтрам
- Headless API для интеграции SPA/фронтенд-фреймворков
- Кастомные заголовки фильтров
- Полная поддержка опций MS3 в фильтрах
- TV Index: нормализация значений для фильтрации
- Интеграция с mSearch (морфологический поиск)
- Шифрование пакета (защита от копирования)
- Резолвер метрик для анонимной статистики установок
- Mass operations для словоформ
- Автодополнение при выборе страницы в SEO-редакторе
- Переключатель шаблонов (grid/list) и lazy-loading дерева ресурсов
- Профилировщик производительности
Улучшения
- Удалён deprecated сервис
MflPageConfig(миграция наFilterSetManager) - JS: кастомный URL-разделитель из системных настроек
- Рефакторинг настроек:
mfl_*→mfilter.* - SEO: логика canonical URL для фильтрованных страниц
- SEO: рефакторинг noindex-настроек
- SEO: человекочитаемые метки для
parentиvendor_id - Админка: фикс фильтра ключа в списке слагов
- mFilterForm: автоопределение текущего ресурса
- Улучшены типы фильтров: vendors, parents, colors, date
- Строгая валидация URL: 404 для несуществующих значений
- CSS-изоляция для совместимости с ExtJS
- Автоподключение фронтенд-ассетов (паттерн MS3)
- Автоустановка зависимостей при установке пакета
- Рефакторинг админки: статус в шапке, удалена вкладка Tools
Исправления
- Зарезервированные слова MySQL 8
- Совместимость xPDO-паттернов
- Обработка date-фильтров
- Парсинг TV
- Инициализация вывода шаблона (
tpl) - Алиасы и генератор
limitв AJAX-URL ответа
1.0.0-beta1
Первый публичный релиз.
- SEO-friendly URL для фильтрованных страниц
- Множество типов фильтров: default, number, boolean, parents, date, vendors, colors
- Поддержка русских словоформ через morpher.ru API
- Vue 3 админка с PrimeVue
- AJAX-фильтрация с History API
- Адаптивная мобильная боковая панель фильтров
- Многозонное обновление контента
- Настраиваемые URL-паттерны на фильтр
- Автогенерация слагов
- SEO-шаблоны с плейсхолдерами и склонениями
- Конфигурация фильтров на уровне страницы
- Управление кэшем и инвалидация
- Интеграция с MODX Scheduler для фоновых задач




Последние обсуждения в сообществе MODX.pro