Диагностика задачи: зачем изменять атрибуты товаров по ролям
В WooCommerce часто требуется показывать разные характеристики товаров разным группам пользователей. Например, оптовые покупатели могут видеть дополнительные атрибуты или скрывать некоторые характеристики, а розничные — стандартный набор. Без кастомизации WooCommerce показывает одинаковые атрибуты всем.
Если вы замечаете, что атрибуты товара не меняются в зависимости от роли, скорее всего, отсутствует нужная логика в шаблонах или не используются фильтры для динамического изменения вывода.
Пошаговое решение: изменение атрибутов товара по роли пользователя
1. Определяем роль текущего пользователя
Для начала нужно узнать, под какой ролью зашел пользователь:
function get_current_user_role() {
if ( is_user_logged_in() ) {
$user = wp_get_current_user();
$roles = ( array ) $user->roles;
return $roles ? $roles[0] : '';
}
return '';
}
2. Фильтруем атрибуты товара для вывода
WooCommerce выводит атрибуты через функцию wc_display_product_attributes(), но она не имеет фильтров для прямой модификации. Поэтому вмешаемся до вызова вывода, изменяя данные атрибутов в объекте WC_Product.
Пример изменения атрибутов на странице товара:
add_filter('woocommerce_product_get_attributes', 'filter_product_attributes_by_user_role', 10, 2);
function filter_product_attributes_by_user_role_by_user_role($attributes, $product) {
$role = get_current_user_role();
if ($role === 'wholesale_customer') { // пример роли оптовика
// Удаляем атрибут "Цвет"
foreach ($attributes as $key => $attribute) {
if ($attribute->get_name() === 'pa_color') {
unset($attributes[$key]);
}
}
// Добавим атрибут "Оптовая скидка"
$attributes['pa_wholesale_discount'] = new WC_Product_Attribute();
$attributes['pa_wholesale_discount']->set_name('pa_wholesale_discount');
$attributes['pa_wholesale_discount']->set_options(array('10%'));
$attributes['pa_wholesale_discount']->set_visible(true);
$attributes['pa_wholesale_discount']->set_variation(false);
}
return $attributes;
}
3. Кеширование и производительность
Если на сайте включено кеширование, убедитесь, что кеш разный для ролей пользователей (например, Vary по Cookie или JS-инъекции), иначе изменения атрибутов не будут видны.
Проверка результата после внедрения
- Залогиньтесь под пользователем с ролью
wholesale_customerи откройте страницу товара. Атрибут "Цвет" должен отсутствовать, а "Оптовая скидка" — отображаться. - Залогиньтесь под обычным пользователем — должны отображаться стандартные атрибуты без изменений.
- Используйте инструменты разработчика браузера, чтобы проверить, что HTML-вывод атрибутов соответствует изменённым данным.
Частые ошибки и как их исправить
- Ошибка: Атрибуты не меняются для нужной роли.
- Проверьте корректность названия роли в условии.
- Убедитесь, что функция
get_current_user_role()возвращает нужное значение.
- Ошибка: Новый атрибут не отображается.
- Проверьте, что атрибут зарегистрирован в WooCommerce (в разделе "Атрибуты" админки).
- Убедитесь, что установлен флаг
set_visible(true).
- Ошибка: Кеширование мешает увидеть изменения.
- Отключите кеш или настройте его для раздельного кеширования по ролям.
Практические советы по безопасности и производительности
- Не используйте тяжелые вычисления или запросы к базе в фильтре изменения атрибутов — лучше заранее подготовить данные.
- Для кеширования динамического контента по ролям используйте фрагментное кеширование или AJAX-загрузку атрибутов после загрузки страницы.
- Проверяйте, что добавляемые атрибуты не раскрывают конфиденциальную информацию для неподходящих ролей.
Сравнение подходов: плагин vs код vs чистый WooCommerce
| Метод | Плюсы | Минусы |
|---|---|---|
| Код (фильтры и хуки) | Полный контроль, нет зависимости от плагинов, легко кастомизировать | Требует навыков PHP, возможны ошибки, нужно учитывать кеш |
| Плагины для кастомизации атрибутов | Простая настройка, поддержка, готовые интерфейсы | Может не покрывать все сценарии, нагрузка, обновления |
| Стандартный WooCommerce | Простота, стабильность | Нет динамической подстройки под роли |