Описание проблемы
В Vue-гриде «Товары категории» (менеджер) не отображаются товары, привязанные к категории только как дополнительной (таблица ms3_category_members, модель msCategoryMember). В карточке товара такая привязка видна, на витрине после фикса #736 сниппета msProducts тоже работает, но в админском гриде категории — нет.
Источник: MODX.Pro #25216 (комментарий пользователя на 1.12.0-beta1, июль 2026).
Шаги воспроизведения
- Создать категорию A и категорию B.
- Создать товар с основной категорией A.
- В карточке товара на вкладке «Категории» отметить категорию B как дополнительную (запись в
ms3_category_members).
- Открыть категорию B в менеджере → грид товаров категории.
- Убедиться, что товар не попадает в список (при
nested=0 и nested=1).
Ожидаемое поведение
Грид категории B показывает:
- товары с
parent = B;
- товары, у которых B указана в
ms3_category_members (как на витрине через msProducts и в логике опций через OptionCategoryService::getProductsInCategory()).
Фактическое поведение
CategoryProductsListService::buildProductListQuery() фильтрует только по msProduct.parent:
if ($nested) {
$c->where(['msProduct.parent:IN' => $categoryIds]);
} else {
$c->where(['msProduct.parent' => $categoryId]);
}
Дополнительные категории (msCategoryMember) не учитываются.
Скриншоты
Не приложены.
Окружение
- MiniShop3: 1.12.0-beta1 и новее (проблема в текущем
main)
- MODX: 3.x
- PHP: 8.2+
- MySQL: 5.7+ / MariaDB 10.3+
Логи ошибок
Логи из core/cache/logs/error.log
Ошибок в логах нет — это логическая недоработка выборки, а не исключение runtime.
Дополнительный контекст
Анализ
| Слой |
Файл |
Учитывает msCategoryMember |
Витрина, msProducts |
elements/snippets/ms3_products.php |
✅ (с ~1.2.3, changelog 2026-01) |
| Опции / синхронизация |
Services/Option/OptionCategoryService.php → getProductsInCategory() |
✅ |
| Дерево категорий в карточке товара |
Processors/Category/GetNodes.php |
✅ |
| Грид товаров категории |
Services/Category/CategoryProductsListService.php |
❌ |
При рефакторинге Product\GetList (changelog, удаление non-combo ветки) join с msCategoryMember убрали из legacy-процессора, но в новый CategoryProductsListService эквивалентную логику не перенесли.
Предложенное решение
- В
CategoryProductsListService::buildProductListQuery() расширить фильтрацию по категории:
- non-nested:
(msProduct.parent = :categoryId OR EXISTS/IN по ms3_category_members WHERE category_id = :categoryId);
- nested:
(msProduct.parent IN (:ids) OR msCategoryMember.category_id IN (:ids)).
- Предпочтительно переиспользовать уже существующий метод
OptionCategoryService::getProductsInCategory() или вынести общий helper (чтобы не дублировать SQL из сниппета ms3_products.php).
- Для
COUNT(DISTINCT msProduct.id) и списка без option-колонок учесть возможные дубликаты при JOIN (как уже сделано для option-колонок через GROUP BY msProduct.id).
- Проверить связанные операции грида:
- drag-sort (
CategoryProductsController::sort) сейчас ищет товар только с parent = categoryId — для товаров из доп. категорий сортировка может не сработать (отдельный edge case, можно описать в PR).
- Добавить unit/integration-тест на выборку товаров категории с
msCategoryMember.
Связанные места в коде
core/components/minishop3/src/Services/Category/CategoryProductsListService.php — основное место правки
core/components/minishop3/src/Services/Option/OptionCategoryService.php — эталонная логика getProductsInCategory()
core/components/minishop3/elements/snippets/ms3_products.php — аналогичный workaround для pdoTools на витрине
Описание проблемы
В Vue-гриде «Товары категории» (менеджер) не отображаются товары, привязанные к категории только как дополнительной (таблица
ms3_category_members, модельmsCategoryMember). В карточке товара такая привязка видна, на витрине после фикса #736 сниппетаmsProductsтоже работает, но в админском гриде категории — нет.Источник: MODX.Pro #25216 (комментарий пользователя на
1.12.0-beta1, июль 2026).Шаги воспроизведения
ms3_category_members).nested=0иnested=1).Ожидаемое поведение
Грид категории B показывает:
parent = B;ms3_category_members(как на витрине черезmsProductsи в логике опций черезOptionCategoryService::getProductsInCategory()).Фактическое поведение
CategoryProductsListService::buildProductListQuery()фильтрует только поmsProduct.parent:Дополнительные категории (
msCategoryMember) не учитываются.Скриншоты
Не приложены.
Окружение
main)Логи ошибок
Логи из core/cache/logs/error.log
Дополнительный контекст
Анализ
msCategoryMembermsProductselements/snippets/ms3_products.phpServices/Option/OptionCategoryService.php→getProductsInCategory()Processors/Category/GetNodes.phpServices/Category/CategoryProductsListService.phpПри рефакторинге
Product\GetList(changelog, удаление non-combo ветки) join сmsCategoryMemberубрали из legacy-процессора, но в новыйCategoryProductsListServiceэквивалентную логику не перенесли.Предложенное решение
CategoryProductsListService::buildProductListQuery()расширить фильтрацию по категории:(msProduct.parent = :categoryId OR EXISTS/IN по ms3_category_members WHERE category_id = :categoryId);(msProduct.parent IN (:ids) OR msCategoryMember.category_id IN (:ids)).OptionCategoryService::getProductsInCategory()или вынести общий helper (чтобы не дублировать SQL из сниппетаms3_products.php).COUNT(DISTINCT msProduct.id)и списка без option-колонок учесть возможные дубликаты при JOIN (как уже сделано для option-колонок черезGROUP BY msProduct.id).CategoryProductsController::sort) сейчас ищет товар только сparent = categoryId— для товаров из доп. категорий сортировка может не сработать (отдельный edge case, можно описать в PR).msCategoryMember.Связанные места в коде
core/components/minishop3/src/Services/Category/CategoryProductsListService.php— основное место правкиcore/components/minishop3/src/Services/Option/OptionCategoryService.php— эталонная логикаgetProductsInCategory()core/components/minishop3/elements/snippets/ms3_products.php— аналогичный workaround для pdoTools на витрине