Диагностика задачи: почему нужно исключать товары по метаданным из связанных товаров WooCommerce
Часто в интернет-магазинах на WooCommerce возникает необходимость исключить определённые товары из блока связанных товаров на странице товара. Это могут быть товары с определённым статусом, помеченные специальным мета-полем, или товары, которые не должны отображаться вместе с текущим из-за особенностей ассортимента.
По умолчанию WooCommerce не предоставляет удобного способа фильтрации связанных товаров по метаданным. Для решения этой задачи необходимо вмешаться в запрос связанных товаров с помощью хуков WordPress и WooCommerce.
Пошаговое решение: исключение товаров по метаданным из связанных товаров
1. Определение мета-ключа и значения
Для примера будем исключать товары с мета-ключом exclude_from_related и значением yes. Это может быть произвольное поле, которое вы добавляете через ACF, CPT UI или вручную.
2. Использование фильтра woocommerce_related_products
Этот фильтр позволяет изменить массив ID связанных товаров перед выводом. Мы получим список связанных товаров, отфильтруем те, у которых есть нужное мета-значение, и вернём обновлённый массив.
add_filter('woocommerce_related_products', 'exclude_related_products_by_meta', 10, 3);
function exclude_related_products_by_meta($related_posts, $product_id, $args) {
$filtered = [];
foreach ($related_posts as $related_id) {
$exclude = get_post_meta($related_id, 'exclude_from_related', true);
if ($exclude !== 'yes') {
$filtered[] = $related_id;
}
}
return $filtered;
}3. Альтернативный подход — фильтрация SQL-запроса
Если требуется более глубокая кастомизация и оптимизация, можно вмешаться в запрос WooCommerce через woocommerce_product_related_posts_query. Это позволит добавить условие meta_query:
add_filter('woocommerce_product_related_posts_query', 'custom_related_products_query', 10, 2);
function custom_related_products_query($query, $product_id) {
if (!isset($query['meta_query'])) {
$query['meta_query'] = [];
}
$query['meta_query'][] = [
'key' => 'exclude_from_related',
'value' => 'yes',
'compare' => '!='
];
return $query;
}Проверка результата после внедрения
Для проверки, что исключение работает:
- Добавьте мета-поле
exclude_from_relatedсо значениемyesдля нескольких товаров через админку или программу для работы с базой. - Откройте страницу товара, который показывает связанные товары.
- Проверьте, что товары с этим мета-полем отсутствуют в блоке связанных товаров.
- Для отладки можно временно добавить
var_dump($related_posts)в фильтр, чтобы увидеть, какие ID проходят через фильтрацию.
Частые ошибки и как их исправить
- Ошибка: Метаполе не добавлено корректно или имеет другое имя.
Решение: Проверьте точное имя мета-ключа через phpMyAdmin или плагин Custom Fields и используйте именно его. - Ошибка: Плагин кеширования или объектный кеш не сбрасывают кэш.
Решение: Очистите кеш сайта и браузера. Для проверки работы фильтра временно отключите кеширование. - Ошибка: Связанные товары не отображаются вообще.
Решение: Убедитесь, что после фильтрации остался непустой массив ID. Если нет, добавьте fallback, например, выводите стандартный блок без фильтрации. - Ошибка: Фильтр не работает из-за приоритета или конфликта с другими плагинами.
Решение: Попробуйте изменить приоритет фильтра (например, 20 вместо 10) или временно отключить сторонние плагины для поиска конфликта.
Практические советы по производительности и безопасности
- При большом количестве товаров обращение к метаданным в цикле
woocommerce_related_productsможет замедлить сайт. Используйте фильтрwoocommerce_product_related_posts_queryдля добавления meta_query и снижения нагрузки. - Не храните в метаполях большие массивы или сложные структуры — это усложняет запросы и увеличивает время загрузки.
- Обязательно проверяйте, что мета-значения корректны и не содержат уязвимостей (например, XSS), если они выводятся в шаблонах.
- Если используете код в functions.php, сделайте резервную копию перед изменениями и применяйте их на тестовом сайте.
Сравнение подходов фильтрации связанных товаров по метаданным
| Метод | Плюсы | Минусы | Использование |
|---|---|---|---|
Фильтр woocommerce_related_products | Простота, быстрый старт без сложных запросов | Может быть медленнее на больших сайтах из-за вызова get_post_meta в PHP цикле | Малые и средние проекты, быстрые правки |
Фильтр woocommerce_product_related_posts_query с meta_query | Оптимизация запроса, лучше для больших баз | Сложнее в реализации, требует понимания WP_Query | Крупные магазины, оптимизация нагрузки |