Диагностика проблемы: почему нужно исключать товары из связанных
В стандартной реализации WooCommerce связанные товары подбираются на основе категорий и тегов, что не всегда подходит для всех бизнес-сценариев. Например, нужно исключить из списка связанные товары, которые являются акционными, устаревшими или с определёнными метаданными (например, товары с флагом "не показывать в рекомендациях"). Без фильтрации пользователь увидит нерелевантные товары, что снижает конверсию и ухудшает пользовательский опыт.
Как WooCommerce подбирает связанные товары
По умолчанию WooCommerce выводит связанные товары с помощью функции wc_get_related_products(), которая берёт ID товаров из тех же категорий и тегов. Для кастомизации результата необходимо использовать фильтр 'woocommerce_related_products' или перезаписать логику SQL-запроса.
Пошаговое решение: исключение товаров по метаданным
1. Добавляем пользовательское метаполе к товарам
Например, метаполе _exclude_from_related с типом yes/no управляет показом товара в связанных.
2. Фильтруем массив связанных товаров
Используем хук woocommerce_related_products для исключения товаров с метаполем _exclude_from_related = 'yes'.
add_filter('woocommerce_related_products', 'exclude_products_by_meta_from_related', 10, 3);
function exclude_products_by_meta_from_related($related_posts, $product_id, $args) {
foreach ($related_posts as $key => $related_id) {
$exclude = get_post_meta($related_id, '_exclude_from_related', true);
if ('yes' === $exclude) {
unset($related_posts[$key]);
}
}
// Возвращаем массив с переиндексацией ключей
return array_values($related_posts);
}
3. Проверяем, что решение работает
- В админке у нескольких товаров поставьте метаполе
_exclude_from_relatedв 'yes'. - Откройте страницу товара, где эти товары могли бы показываться как связанные.
- Убедитесь, что товары с метаполем 'yes' не отображаются в блоке связанных.
Альтернативный вариант: модификация SQL запроса
Если нужно более сложное исключение, можно использовать фильтр 'woocommerce_related_products_args', чтобы изменить параметры WP_Query, например:
add_filter('woocommerce_related_products_args', 'modify_related_products_query_args', 10, 1);
function modify_related_products_query_args($args) {
$args['meta_query'][] = array(
'key' => '_exclude_from_related',
'value' => 'yes',
'compare' => '!=',
);
return $args;
}
Этот метод исключит товары по метаданным ещё на уровне запроса, что эффективнее при большом количестве товаров.
Проверка результата после внедрения
- Откройте несколько товаров, чтобы проверить, что исключённые товары не показываются.
- Для отладки используйте функцию
var_dump($related_posts)внутри фильтра, чтобы увидеть итоговый массив ID. - Убедитесь, что пагинация и прочие элементы блока связанных работают без ошибок.
Частые ошибки и как их исправить
- Метаполе не задано или задано неправильно: проверьте через
get_post_meta(), что метаданные действительно установлены и читаются. - Неправильный приоритет фильтра: при необходимости увеличьте приоритет до 20-30, чтобы фильтр сработал после других.
- Не выполняется переиндексация массива после
unset(): всегда возвращайтеarray_values(), иначе WP может не корректно обработать массив. - Фильтр
'woocommerce_related_products_args'не работает: убедитесь, что используете последнюю версию WooCommerce, и что фильтр не переопределяется другими плагинами.
Практические советы по производительности и безопасности
- Если у вас большой каталог, лучше исключать товары уже на уровне SQL-запроса (через
woocommerce_related_products_args), чтобы не загружать лишние данные. - Храните метаполя в виде простых строк или чисел для быстрого поиска.
- Не используйте сложные условия в цикле PHP, чтобы избежать замедления загрузки страницы.
- Проверяйте, что исключение товаров не приводит к пустому блоку связанных — на случай, если все связанные товары будут исключены, рассмотрите fallback-логику.
Сравнение методов исключения товаров из связанных
| Метод | Плюсы | Минусы | Когда использовать |
|---|---|---|---|
Фильтр woocommerce_related_products (PHP) |
Просто реализуется, можно гибко фильтровать после получения ID. | Загружаются все связанные, фильтрация в PHP — нагрузка на сервер. | Небольшие каталоги, простая логика исключения. |
Фильтр woocommerce_related_products_args (SQL) |
Исключение на уровне запроса, лучше масштабируемость и производительность. | Сложнее в реализации, ограниченные возможности фильтрации. | Большие каталоги, критична производительность. |