
mFilter 1.5.0
Главное
Индивидуальные SEO-страницы для подборок. Собственные title, h1, description и текст для конкретной комбинации фильтров — например, только для страницы одного цвета. Раньше это требовало стороннего плагина со своей таблицей.
Новая вкладка в админке — SEO-страницы.
Новые возможности
Индивидуальные SEO для подборок
Заполненное поле перекрывает SEO-шаблон, незаполненное — оставляет его значение. Каждое поле проходит цепочку «индивидуальная запись → шаблон → значение по умолчанию» самостоятельно. Чтобы поменять только заголовок, достаточно заполнить один H1: при правке шаблона такие страницы обновятся вместе со всеми.
Записи создаются по требованию. Страница с одним фильтром и сорока значениями даёт сорок адресов, и заводить под них пустые строки значило бы засорить базу. Список подборок строится на лету из фильтров страницы; строка попадает в базу при первом сохранении, а очистка всех полей её удаляет.
Запись привязана к значению фильтра, а не к URL. Переименование слага, смена mfilter.url_separator или режима mfilter.slug_parent_prefix меняют адрес страницы, но запись продолжает работать.
Список перечисляет подборки по одному значению одного фильтра. Диапазоны и сочетания нескольких значений не перечисляются: между границами диапазона адресов бесконечно много, а сочетания растут мультипликативно.
Запись снимает noindex, навешенный mfilter.seo_max_filters или mfilter.seo_max_values, и восстанавливает canonical на саму отфильтрованную страницу. Настройка mfilter.seo_noindex_filtered сильнее в любом случае: если владелец закрыл все фильтрованные страницы, текст в поле этого не отменяет.
Если значение исчезло из каталога, запись не удаляется — помечается в списке и остаётся.
Чанк формы знает о состоянии фильтров
В tplOuter сниппета mFilterForm появились $hasFilters, $activeFiltersCount и $appliedFilters — кнопку сброса можно показывать только когда что-то выбрано:
<button type="reset" class="btn" data-mfilter-reset{if !$hasFilters} hidden{/if}>
Сбросить (<span data-mfilter-reset-count>{$activeFiltersCount}</span>)
</button>Штатного способа раньше не было: плейсхолдер mfilter.activeCount выставляется после рендера чанка, а mfilter.filters заполняется только при разборе SEO-URL. Новые переменные собираются из обоих источников.
Внимание
Кнопку нужно рендерить всегда и скрывать атрибутом hidden. Обёрнутую в {if $hasFilters} кнопку JS не найдёт в DOM и показать не сможет.
Счётчик считает диапазон за один фильтр: price|min и price|max схлопываются в price.
Разрешение конфликтов слагов
Две категории с одинаковым названием в разных ветках давали один и тот же слаг. Второй INSERT падал на уникальном индексе, запись не создавалась, и в URL подставлялся числовой ID вместо человекочитаемого адреса.
Конфликт теперь разрешается до записи. Поведением управляет новая настройка mfilter.slug_parent_prefix:
| Режим | Поведение |
|---|---|
on_conflict (по умолчанию) | Обычный слаг; при конфликте добавляется родитель — topki-axis. Существующие URL не меняются |
always | Родитель добавляется всегда — pechi-axis. Меняет существующие URL, потребуются 301-редиректы |
never | Только числовой суффикс — axis-2 |
Префикс родителя доступен там, где значение фильтра — ID ресурса. Раньше это решалось двумя захардкоженными списками ключей, которые разъехались с реальными типами фильтров. Теперь тип сообщает о себе сам — новый метод FilterTypeInterface::getValueKind():
| Вид значения | Слаг для числового | Префикс родителя | Типы |
|---|---|---|---|
resource | да | да | parents, ms3_categories |
entity | да | нет | vendors |
scalar (по умолчанию) | нет | нет | все остальные |
Для сторонних типов ничего не ломается: scalar объявлен в AbstractFilterType.
Прочее
- Понятная ошибка при ручном вводе занятого слага: 409 с текстом «Слаг «axis» уже занят значением «124»» вместо безликой ошибки 500.
- Фильтр по источнику и сортировка по колонке «Источник» во вкладке «Алиасы».
- Параметр
&searchVarсниппетаmFilterзадаёт имя параметра запроса с поисковой фразой — раньше было жёсткоmse_query. - Кнопку сброса формы можно помечать атрибутом
data-mfilter-resetнаравне с классомmfilter-reset-btn.
Исправления
SEO
- SEO-шаблон не срабатывал на страницах с диапазоном. Шаблон подбирается по ключам фильтров, а SEO-адрес отдаёт диапазон двумя записями —
price|minиprice|max. Шаблон, настроенный наprice, не совпадал ни с одной. Границы теперь сворачиваются к базовому ключу перед подбором. - Диапазон в заголовке читается по-человечески: «10600 — 15500», «от 10600», «до 15500» — через новые лексиконы
mfl_seo_range_from,mfl_seo_range_to,mfl_seo_range_separator. - Приоритет SEO-шаблонов не работал — сортировка шла по несуществующему полю. Теперь по
sort_order, где меньше значит выше. - Поле «Шаблон текста» в SEO-шаблонах не сохранялось: оно отсутствовало в карте полей модели xPDO, а xPDO молча отбрасывает поле, которого не знает.
- Переустановка пакета ломала все SEO-шаблоны — колонка добавлялась только при обновлении, а таблицы при удалении компонента сохраняются намеренно.
- SEO-текст не очищался при снятии фильтров, а на пустой выдаче AJAX-ответ не нёс ни SEO, ни адресов — на странице оставались заголовок и текст предыдущей подборки.
- Неразобранный сегмент URL влиял на SEO: служебный ключ
_hiddenдоходил до заголовка, участвовал в подсчёте лимитов индексации и попадал в canonical.
Фильтрация и вывод
- С параметром
elementкаталог рендерился пустым.mFilterбезусловно передавал элементу свои значенияshowHidden/showUnpublished/showDeleted, перекрывая его собственные. Флаги теперь пробрасываются только когда заданы явно. - Сортировка каталога при AJAX работала только внутри страницы — элемент не получал текущую сортировку и отдавал ID в порядке по умолчанию.
- При AJAX сбрасывались чанки, лимит и scope в native-режиме. Оба режима теперь используют общее хранилище конфига вызова.
data-totalиdata-page-countпротухали после AJAX — атрибуты обёртки синхронизируются на каждом обновлении.- Дублирование фильтров в URL и в блоке «Выбрано» для мультизначных фильтров. Заодно
utm_*иgclidбольше не попадают в состояние фильтров. - Warmup мог вернуть пустой каталог: параметры авто-конфигов не обновлялись при расхождении. Пустой результат прогрева больше не кэшируется.
Блок «Выбрано»
Разметка сбрасывалась на дефолтные чанки при фильтрации.
SelectedFilters.jsсодержал копию четырёх стандартных чанков и пересобирал блок из неё при каждом AJAX-ответе, поэтому кастомная разметка жила до первого клика по фильтру.Дублирование убрано: блок рендерится на сервере теми же чанками, что и при первой загрузке. Обратная совместимость полная — если в
tplOuterнет атрибутаdata-mfilter-selected-hash, работает прежний клиентский рендер:html<div class="mfilter-selected" data-mfilter-selected {if $hash} data-mfilter-selected-hash="{$hash}"{/if}>Кнопка «Сбросить всё» не работала на странице, отфильтрованной только диапазоном.
В блок при AJAX попадали посторонние ключи, включая служебный
_hidden.{$count}расходился с числом применённых фильтров.Подписи значений для категорий MS3 и производителей показывали сырой ID.
Внимание при обновлении
Заголовки страниц с диапазоном изменятся
Страницы, отфильтрованные по диапазону, раньше не подбирали SEO-шаблон и генерировали заголовок по умолчанию. Теперь шаблон, настроенный на базовый ключ (price), к ним применяется — h1, title и description таких страниц изменятся, в том числе у уже проиндексированных.
Формат ключа кэша baseIds изменился
Ключ стал учитывать сортировку. После обновления первый запрос каждой сортировки пересчитает выборку.
mFilter 1.5.1
Патч к 1.5.0. Все исправления касаются переменных и настроек, которые documented-поведением обещаны, но до места назначения не доходили.
Исправления
Переменные, заявленные в документации, не доходили до чанков. Четыре штуки, все одного вида: значение читалось из источника, которого не существует, и молча подменялось запасным.
Чанк Переменная Что выводилось tplSlider$labelключ фильтра вместо названия из поля «Заголовок» tplSlider$prefix,$suffixпусто при любых настройках tplReset(«Выбрано»)$urlпусто — переменная не передавалась вовсе tplOuter(«Выбрано»)$totalпусто — передавался только $count$hexв чанке цветового свотча ставился не всегда — теперь приходит всегда, пустой строкой.$filtersвtplOuterсниппетаmFilterсуществовал только в native-режиме.Ссылки пагинации вели в 404 на сайтах с нестандартным разделителем. Чанк
mfilter.paginationсобирал сегмент какpage_2, игнорируяmfilter.url_separator. Изнутри сайта дефект незаметен: JS перехватывает клик и строит адрес сам, минуя роутер. В 404 попадали при прямом открытии — из закладки, новой вкладки или поиска.Настройка
mfilter.default_limitне влияла на размер страницы. Её читали роутер,UrlBuilderи native-режим, но не сниппет — там было зашито 20. Теперь настройка задаёт значение по умолчанию для&limit, а переданный&limitеё перекрывает. Значение доводится и до AJAX, иначе первая отрисовка и первый клик по фильтру дали бы разные размеры страницы.Селект сортировки и переключатель вида в
mfilter.outerвсегда показывали значения по умолчанию — чанк читал$_pls['mfilter.sort']и$_pls['mfilter.tpl'], а этих ключей в данных чанка нет. Сниппет теперь передаёт$currentSortи$currentTpl.&pageParamне доходил до чанка пагинации в element-режиме.
Внимание при обновлении
Чанки не перезаписываются
Стандартные чанки при обновлении компонента не затираются — правки в mfilter.pagination и mfilter.outer дойдут только до новых установок. Сайтам со своей копией их нужно обновить вручную, иначе:
- в
mfilter.paginationостанется зашитыйpage_, и ссылки пагинации продолжат отдавать 404 при прямом открытии; - в
mfilter.outerостанется собственное{var $currentSort = $_pls['mfilter.sort'] ?: 'pagetitle-asc'}, которое перекроет переданную переменную своим же значением по умолчанию — молча, без ошибок.
$_pls в шаблоне и в чанке — разные массивы
Не изменение поведения, а причина, по которой разметка, перенесённая из чанка в шаблон ресурса, ломается. Подробности — в Плейсхолдерах.
Не дублируйте обёртку data-mfilter-results в шаблоне. Получатся два вложенных контейнера, JS привяжется к внешнему, а data-mfilter-hash в нём будет пуст. AJAX без хэша не находит сохранённую конфигурацию вызова и уходит в native-режим — в выдачу попадают категории и прочие ресурсы, которых не было при первой загрузке.
Подписи над слайдерами изменятся
Там, где в чанке слайдера стоит {$label}, вместо ключа фильтра появится его название — price сменится на «Цена».
Отдельно про $hex: он теперь приходит всегда, пустой строкой вместо отсутствия. Чанк с проверкой {if isset($hex)} пойдёт по истинной ветке в любом случае — проверять надо {if $hex}.
