Авг
4
74

Хаки для вариаций товаров в WooCommerce

Вариации товара в WooCommerceРанее я уже рассматривал создание вариативного товара в WooCommerce, когда пользователю доступен выбор разных значений атрибутов (цвет, вес) для продукции интернет-магазина. Добавить подобную фишку на сайт можно с помощью базовых функций модуля. Тем не менее, в ходе работы иногда возникают нюансы и задачи, когда придется внедрять дополнительные хаки. Именно об этих решениях для WooCommerce вариаций товаров мы сегодня и поговорим. 

По аналогии с постом про кнопку добавить в корзину соберу несколько сниппетов в рамках одной заметки. Причем все они частично будут между собой пересекаются + есть задачи, которые решаются с разными подходами. Поэтому рекомендую данный пост читать максимально вдумчиво со всеми пояснениями! Содержание:

Вывод минимальной цены для всех вариаций

Некоторые заказчики хотят реализовать в своем магазина фишку, когда на странице каталога настроен вывод вариаций товара WooCommerce только с минимальной ценой. Во-первых, это маркетинговый ход дабы показывать наименьшую стоимость. Во-вторых, сможете сэкономить немного места в шаблоне, отображая лишь одну цену.

Отображение минимальной цены товара в WooCommerce

Изначально в этом посте рассказывал о сниппете, который решал проблему только в архиве/категориях, а для страницы товаров я все настраивал в шаблоне. Данный «глобальный» подход «закрывает» сразу несколько подзадач по этой теме.

Код публикую частями (чтобы было проще объяснять суть), а вы вставляйте эти блоки в файл функций темы functions.php подряд друг за другом в такой же очередности.

function bbloomer_variation_price_format( $price, $product ) {
 
 if (is_product()) {
    return $product->get_price();
 } else {
        // Main Price
        $prices = array( $product->get_variation_price( 'min', true ), $product->get_variation_price( 'max', true ) );
        $price = $prices[0] !== $prices[1] ? sprintf( __( '%1$s', 'woocommerce' ), wc_price( $prices[0] ) ) : wc_price( $prices[0] );
 
        // Sale Price
        $prices = array( $product->get_variation_regular_price( 'min', true ), $product->get_variation_regular_price( 'max', true ) );
        sort( $prices );
        $saleprice = $prices[0] !== $prices[1] ? sprintf( __( '%1$s', 'woocommerce' ), wc_price( $prices[0] ) ) : wc_price( $prices[0] );
 
        if ( $price !== $saleprice ) {
        $price = '<del>' . $saleprice . '</del> <ins>' . $price . '</ins>';
        }
        return $price;
         }
}
 
if ( ! is_admin() ) {
    add_filter( 'woocommerce_variable_sale_price_html', 'bbloomer_variation_price_format', 10, 2 );
    add_filter( 'woocommerce_variable_price_html', 'bbloomer_variation_price_format', 10, 2 );
}

Здесь:

  • Во-первых, функция учитывает наличие скидочной цены: если она активна, то пользователь увидит перечеркнутой базовую стоимость, а рядом будет стоять ценник со скидкой.
  • Во-вторых, в начале есть условие is_product, за счет которого наши действия сработают для всех страниц кроме единичного продукта (там свои нюансы).
  • В-третьих, ниже мы видим еще один условный оператор is_admin чтобы все это «происходило» только на сайте, а НЕ в админке.
// show variation price
add_filter('woocommerce_show_variation_price', function() {return true;});
 
//override woocommerce function
function woocommerce_template_single_price() {
    global $product;
    if ( ! $product->is_type('variable') ) { 
        woocommerce_get_template( 'single-product/price.php' );
    }
}

Второй блок состоит из двух решений. Если я правильно понял логику первой строки, то там мы избавляемся от глюка, когда все вариативные цены одинаковые и, как следствие, не показываются на странице (кому нужен данный хак отдельно, ищите ниже).

С помощью переопределения функции woocommerce_template_single_price мы будем выводить для вариаций такой же блок шаблона, что и для простой продукции. Также, вероятно, где-то здесь избавляемся от двойного отображения стоимости у вариативных товаров.

function shuffle_variable_product_elements(){
    if ( is_product() ) {
        global $post;
        $product = wc_get_product( $post->ID );
        if ( $product->is_type( 'variable' ) ) {
            remove_action( 'woocommerce_single_variation', 'woocommerce_single_variation', 10 );
            add_action( 'woocommerce_before_variations_form', 'woocommerce_single_variation', 20 );
 
            remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_title', 5 );
            add_action( 'woocommerce_before_variations_form', 'woocommerce_template_single_title', 10 );
 
            remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_excerpt', 20 );
            add_action( 'woocommerce_before_variations_form', 'woocommerce_template_single_excerpt', 30 );
        }
    }
}
add_action( 'woocommerce_before_single_product', 'shuffle_variable_product_elements' );

Финальный блок, как и остальные части, позаимствованы отсюда. Внимание! Он НЕ обязательно должен быть именно таким – все зависит от вашего шаблона. Тут важно понять суть происходящего в нем.

Специфика ситуации в том, что вариативные товары являются динамическим элементом страницы и редактируются через JavaScript файл add-to-cart-variation.js. Данный элемент помещается внутрь блока <div class=»woocommerce-variation single_variation»>, который в свою очередь должен оставаться внутри формы с классом variations_form. Поэтому и производятся все эти переносы блоков на странице товара.

Как я уже сказал выше, совсем не обязательно использовать весь этот код. Удаляйте/перемещайте только те блоки, которые вам не нужны. В моем случае хватило таких строк (первые 2 точно нужны, а код с title и excerpt — при необходимости):

function shuffle_variable_product_elements(){
    if ( is_product() ) {
        global $post;
        $product = wc_get_product( $post->ID );
        if ( $product->is_type( 'variable' ) ) {
            remove_action( 'woocommerce_single_variation', 'woocommerce_single_variation', 10 );
            add_action( 'woocommerce_before_variations_form', 'woocommerce_single_variation', 20 );
        }
    }
}
add_action( 'woocommerce_before_single_product', 'shuffle_variable_product_elements' );

Отображение только минимальной цены в рубриках/категориях

Самый просто вариант, который можно здесь придумать это:

Метод1

add_filter('woocommerce_variable_price_html', 'mycustom_variation_price', 10, 2);
add_filter('woocommerce_variable_sale_price_html', 'mycustom_variation_price', 10, 2 );
 
function mycustom_variation_price( $price, $product ) {
	if ( ! is_admin() && ((is_shop() || is_product_category() || is_page()))) {
     $price = '';
     $price .= woocommerce_price($product->get_price());
    } 
    return $price;
}

Размещается традиционно в файле functions.php. Здесь вы с помощью хуков заменяете стандартные функции отображения вариаций товара WooCommerce на свою. Также добавляем условие показа только в каталоге (главная, архив, отдельные страницы — is_shop, is_product_category, is_page). Не забываем про исключение из админки (!is_admin).

Вариант, как видите, не учитывает наличие скидочных цен. Если вы хотите отображать новый ценник рядом с перечеркнутым акционным, то тут пригодится следующий хак:

Метод2

/**
 * Change variable product price to display From £#.## instead of price range
 *
 * @param string $price
 * @param \WC_Product_Variable $product
 *
 * @return float|string
 */
function jc_variable_product_price_display($price, $product){
 
	$price_min = $product->get_variation_price( 'min', true );
	$price_sale_min = $product->get_variation_sale_price( 'min', true );
 
	if($product->is_on_sale() && $price_min < $price_sale_min){
	  $price = sprintf('<del>%s</del><ins>%s</ins>', wc_price($price_min), wc_price($price_sale_min));
	}else{
		$price = wc_price($price_min);
	}
 
	return sprintf('From: %s', $price);
}
 
add_filter( 'woocommerce_variable_sale_price_html', 'jc_variable_product_price_display', 10, 2 );
add_filter( 'woocommerce_variable_price_html', 'jc_variable_product_price_display', 10, 2 );

Этот пример взят отсюда и (внимание!) тут нет никаких условных операторов — если вам они нужны, следует их использовать.

У двух этих методик есть ряд «особенностей», на которые следует обратить внимание. Сниппеты могут вносить определенную «неточность» при восприятии информации на сайте. Например:

  • У вас есть вариативный товар стоимостью $10-$30, и посетитель выбирает в фильтрах значение «от $20 и выше». Данная позиция будет отображена на странице в любом случае, но вместо диапазона в цене показывается минимальное знание — $10.
  • Если условиями исключать единичную страницу is_single, то в блоке похожей продукции на ней могут остаться диапазоны цены. Плюс обычную страничку с товаром также нужно как-то обрабатывать при выводе (через глобальный код выше или своими методами).
  • Не забывайте, что хаки применяются и в админке, поэтому без исключения !is_admin не обойтись.
  • В первом случае может перестать работать «перечеркивание» для скидок.

Ну, и напоследок нашел не менее интересный подход:

Метод3

/**
 * @snippet       Variable Product Price Range: "From: <del>$$$min_reg_price</del> $$$min_sale_price"
 * @how-to        Get CustomizeWoo.com FREE
 * @sourcecode    https://businessbloomer.com/?p=275
 * @author        Rodolfo Melogli
 * @compatible    WooCommerce 3.5.4
 * @donate $9     https://businessbloomer.com/bloomer-armada/
 */
 
add_filter( 'woocommerce_variable_price_html', 'bbloomer_variation_price_format', 10, 2 );
 
function bbloomer_variation_price_format( $price, $product ) {
 
// 1. Get min/max regular and sale variation prices
 
$min_var_reg_price = $product->get_variation_regular_price( 'min', true );
$min_var_sale_price = $product->get_variation_sale_price( 'min', true );
$max_var_reg_price = $product->get_variation_regular_price( 'max', true );
$max_var_sale_price = $product->get_variation_sale_price( 'max', true );
 
// 2. New $price, unless all variations have exact same prices
 
if ( ! ( $min_var_reg_price == $max_var_reg_price && $min_var_sale_price == $max_var_sale_price ) ) {   
   if ( $min_var_sale_price < $min_var_reg_price ) {
      $price = sprintf( __( 'From: <del>%1$s</del><ins>%2$s</ins>', 'woocommerce' ), wc_price( $min_var_reg_price ), wc_price( $min_var_sale_price ) );
   } else {
      $price = sprintf( __( 'From: %1$s', 'woocommerce' ), wc_price( $min_var_reg_price ) );
   }
}
 
// 3. Return $price
 
return $price;
}

Отображение цены вариации по умолчанию

Есть еще один способ вывода одной цены вместо диапазона на страницах категорий. Вы можете показывать для вариаций WooCommerce стоимость товара, выбранного по умолчанию. Соответствующая настройка задается в закладке «Вариации»:

Цены вариаций

Я, в принципе, стараюсь всегда указывать этот параметр дабы не возникало никаких «случайных несостыковок» на странице описания продукции магазина. Чтобы выводить данное значение в разделах добавьте в functions.php следующие строки:

add_filter('woocommerce_variable_price_html', 'custom_variation_price_default', 10, 2);
add_filter('woocommerce_variable_sale_price_html', 'custom_variation_price_default', 10, 2 );
 
function custom_variation_price_default( $price, $product ) {
  foreach($product->get_available_variations() as $pav){
      $def=true;
      foreach($product->get_variation_default_attributes() as $defkey=>$defval){
          if($pav['attributes']['attribute_'.$defkey]!=$defval){
              $def=false;             
          }   
      }
      if($def){
          $price = $pav['display_price'];         
      }
  }   
 
  return woocommerce_price($price);
}

Решение найдено тут. По сравнению с предыдущим методом здесь чуть больше кода, но, к сожалению, «неточности» возникают такие же: с фильтрами, отображением товара «не в наличии», показом стоимости в админке. Единственное преимущество, делающее такой подход гибче — возможность выбора вручную какую цену выводить.

Вариации товара с одинаковыми ценами

Не знаю как в новых Woocommerce 3.x, но в предыдущей ветке точно закрался странный глюк. Если у вас имеется товар с несколькими вариациями, для которых установлена одинаковая стоимость, то на странице с его описанием поле цены будет скрыто.

Глюк отображения цены в вариациях

Чтобы это исправить в файл функций добавляем:

add_filter('woocommerce_available_variation', function ($value, $object = null, $variation = null) {
    if ($value['price_html'] == '') {
        $value['price_html'] = '<span class="price">' . $variation->get_price_html() . '</span>';
    }
    return $value;
}, 10, 3);

Повторюсь, у меня этот косяк появляется в Woocommerce 2.6.x, возможно, в следующей версии он уже исправлен. Дополнительно советую глянуть плагин скидок и оптовых цен в WooCommerce.

Если первый вариант не сработает, вот похожий прием:

add_filter( 'woocommerce_show_variation_price', 'filter_show_variation_price', 10, 3 );
function filter_show_variation_price( $condition, $product, $variation ){
    if( $variation->get_price() === "" ) return false;
    else return true;
}

Вариации товара в WooCommerce без выпадающего списка

Я думаю, выпадающий список — не лучший способ выбора вариаций на странице магазина WooCommerce. Как минимум, пользователю приходится делать дополнительное действие для просмотра доступных значений атрибутов, плюс не все смогут сходу сообразить куда нужно кликать и т.п. Поэтому решение с чекбоксами (Radio Buttons) выглядит куда более юзерфрендли.

Вывод вариаций товара в WooCommerce

В сети найдете разные хаки по данной задаче. Однако мне больше всего нравится реализация с помощью модуля — внедряется она максимально просто и быстро. Наибольшее доверие из имеющихся плагинов вызывает WC Variations Radio Buttons.

Плагин WC Variations Radio Buttons

На момент написания статьи последняя версия модуля имела чуть более 3 тысяч загрузок и хорошую оценку. В некоторых шаблонах решение может работать сразу после установки и активации. Если же разработчики внесли свои правки в файл WooCommerce магазина single-product/add-to-cart/variable.php, то вам нужно будет:

  1. Создать дочернюю тему (если ее нет).
  2. Скопировать файл из директории модуля plugins/wc-variations-radio-buttons/templates/single-product/add-to-cart/variable.php в ваш шаблон сюда — themes/ИМЯ_ТЕМЫ/woocommerce/single-product/add-to-cart/variable.php. Если там уже есть такой файл, замените его.

Как правило, в шаблонах магазинов WooCommerce все реализуется через дочерние темы, поэтому с первым пунктом сложностей возникнуть не должно. В дальнейшем я постараюсь этот момент рассмотреть более детально.

Если у вас имеются вопросы по теме поста как вывести вариации товара в WooCommerce, пишите ниже.

рейтинг Оцените статью:
Ужасная статьяНичего интересногоТак себеНормальноХорошоКлассный постВ закладки!
(голосов - 17, средний балл: 5,29 из 7)
Загрузка...

категория Категории: WooCommerce; Хаки и секреты;
теги Теги: , , , , .

комментария 74 к статье “Хаки для вариаций товаров в WooCommerce”

  • Михаил   04.04.2017

    Пытался делать Радиобатоны в ценах через хаки, которые нашел в сети. Один из трех сработал, но пришлось повозиться. Похоже, что с модулем оно попроще будет.

  • Tod   04.04.2017

    Михаил, с плагином WC Variations Radio Buttons оно не то что проще, а элементарно. Активировал модуль, скопировал файл шаблона в дочернюю тему, и все заработало.

  • Елена   24.08.2017

    Добрый день, подскажите как можно переработать этот код, чтобы в категории отображалась базовая цена товара, а не наименьшая?

  • Tod   24.08.2017

    Елена, базовая цена — это какая?

  • Елена   24.08.2017

    Извините, некорректно выразилась. Значение цены в категории = значению атрибута по умолчанию, выставленного в вариациях. Скриншот — http://s019.radikal.ru/i605/1708/73/ef0cd5496ea9.jpg

  • Tod   29.08.2017

    Елена, дополнил статью нужным вам хаком. Если вы еще не нашли решение, попробуйте код из заметки.

  • Елена   30.08.2017

    Спасибо!

  • Роман   01.11.2017

    Здравствуйте! Подскажите, пожалуйста, как реализовать подмен функции кнопки «Выбрать опции» для вариативного товара на «Добавить в корзину», чтоб в корзину падал товар с вариацией по-умолчанию со страницы магазина?

  • Tod   01.11.2017

    Роман, так «выбрать опцию» это не кнопка, а просто текст в выпадающем списке вариаций, не совсем понятно зачем его менять (он служит подсказкой для посетителя). Вы можете установить нужный вариант по умолчанию в настройках товара — заходите в пункт «Вариации», там будет поле «Значения форм по умолчанию». Если его задать, то на сайте сразу же будет отображаться данное значение, а сам текст «выбрать опцию» не покажется. Надеюсь, ответил либо я неправильно понял вопрос.

  • Роман   01.11.2017

    Tod, нет, я не об этом, текст поменять не проблема. Я хочу чтоб пользователь имел возможность добавления вариативного товара в корзину со страницы магазина(архива). То есть, на странице с товарами есть простые и вариативные, простые сразу добавляются в корзину с этой страницы, а вот чтоб добавить вариативный надо зайти на страницу товара, и только от туда его добавить. У товаров немного опций, мне нужно чтоб вариативные товары с опцией по-умолчанию так же добавлялись в корзину как и простые со страницы магазина. Уже давно бьюсь над этой проблемой…

  • Tod   02.11.2017

    Роман, понял, такое к сожалению, не встречал. Я бы погулил что-то типа quick order woocommerce для вариаций.

  • Роман   02.11.2017

    Tod, я уже как только не гуглил… =) Где только не писал, в Stackowerflow, в Toster, еще где-то.
    Я и сам примерно понимаю, что в шаблонах через хуки надо подменить функции, но конкретно какие я не знаю. Видимо придется глубже изучать Woocommerce.

  • Tod   02.11.2017

    Роман, видимо, задача весьма слишком нестандартная и без изучения тут никак не получится.

  • Артем   28.12.2017

    Роман, хотел бы узнать, нашли ли решение вашей задачи? Я тоже искал, так и не нашел.

  • Дмитрий   02.01.2018

    Здравствуйте! А не подскажете, как можно вывести изображения вариаций?

  • Tod   02.01.2018

    Дмитрий, если вы говорите про то, то фотки должны меняться при смене вариаций товаров, то по идее это базовая фишка модуля и достаточно просто в админке задать для каждого вида продукции свое изображение. На ранних версиях плагина (как лично у меня ана 2.6.х) с этой функциональность могут быть проблем, но скорее всего в 3.х их пофиксили.
    Если нужна какая-то другая функциональность, то тут советую поискать соответствующий модуль, возможно, она есть в Booster for WooCommerce.

  • Анна   21.01.2018

    Подскажите, пожалуйста, а как поместить товары без цены в конец
    при сортировке по возрастанию цены

  • Tod   22.01.2018

    Анна, у меня был посто про товары нет в наличии в конце списка, возможно получится как-то модифицировать код. К сожалению, готовое решение подсказать не смогу.

  • Андрей   30.01.2018

    Здравствуйте, подскажите как вывести цены списком в категории (каталоге) ?
    например
    100г — 100руб
    200г — 200руб
    300г — 300руб
    сейчас выводится 100руб-300руб
    нашел код который выводит так как надо, но отображается только цена… а там где Вес пусто
    там автор пишет что : echo $variation_name[«KEY»] Key — ключ выводимой вариации
    подскажите что здесь надо прописать?

  • Tod   30.01.2018

    Андрей, мне сложно сходу подсказать по вашему вопросу. Надо гуглить что за key имелся ввиду.

  • Андрей   30.01.2018

    вот весь код целиком

    $args = array(
    ‘post_type’ => ‘product_variation’,
    ‘post_status’ => array( ‘private’, ‘publish’ ),
    ‘numberposts’ => -1,
    ‘orderby’ => ‘menu_order’,
    ‘order’ => ‘ASC’,
    ‘post_parent’ => get_the_ID() // get parent post-ID
    );
    $variations = get_posts( $args );

    foreach ( $variations as $variation ) {

    // get variation ID
    $variation_ID = $variation->ID;

    // get variations meta
    $product_variation = new WC_Product_Variation( $variation_ID );

    // get variation featured image
    $variation_image = $product_variation->get_image();

    // get variation price
    $variation_price = $product_variation->get_price_html();
    //get variation name
    $variation_name = $product_variation->get_variation_attributes();
    echo «»;
    echo $variation_name[«KEY»].»: «;
    echo ($variation_price);
    echo «»;
    }

  • Tod   31.01.2018

    Андрей, возможно это значение slug для атрибута, из которого и создаются варианты. Ничего больше на ум не приходит. Нужно смотреть синтаксис функции get_variation_attributes что она там выводит. Я с такой задачей не сталкивался.

  • Антон   24.04.2018

    Здравствуйте. А как вывести все цены вариативного товара ( как это делает плагин WC Variations Radio Buttons.) в каталоге товаров, что бы под названием товара были такие же чекбоксы с вариантами цен

  • Tod   24.04.2018

    Антон, без дополнительного программирования никак. Я в коде модуля не копался, но вполне вероятно, что там для вставки цен на страницу товара используется какой-то фильтр/хук. Если так, то теоретически, можно попробовать поменять его на тот вариант, который выводит информацию непосредственно в каталоге товаров. Хотя, мне кажется, что это было бы слишком просто и, вряд ли, замена одной строчки кода решит вашу задачу. Вообще подобных реализаций каталога, признаться, еще не встречал.

  • Артур   28.05.2018

    Час добрый!
    Воспользовался вашим хаком Отображение цены вариации по умолчанию, всё работает, спасибо.
    Однако есть момент. На странице вариативного товара по умолчанию выводится две позиции цены. Одна та что стоит по умолчанию, вторая тоже по умолчанию. Потом когда начинаете выбирать товар по вариациям, одна позиция цены меняется согласно выбранного товара, а вторая всё так же показывает цену по умолчанию, что вносит сумятицу. Пример:

    https://pro-artlife.ru/shop/formula-men/

    Можно как-то сделать, чтобы выводилась только одна позиция товара (та что внизу), а та что сверху убрать?

  • Tod   29.05.2018

    Артур, нужно смотреть каким образом в том месте шаблона выводится вторая цена и для нее также применить фильтр. Либо вообще убрать лишнюю запись. В любом случае придется вникать в файлы шаблона и заниматься его правкой.

  • Влад   01.06.2018

    В карточке товара при выборе атрибута не появляется цена для этого атрибута, то есть только вверху цена от и до и все и ничего не меняется, но при покупке конечно в корзине товар с нужной ценой но как сделать чтобы в карточке товара она менялась при выборе того или иного атрибута, все правильно настроил а она вообще не появляется.

  • Tod   01.06.2018

    Влад, я бы попробовал работу модуля в «чистой среде» — со стандартной темой и без доп.плагинов и посмотрел как ведет себя цена. Нужно понять что именно вызывает данный глюк, т.к. это поведение ненормально. Возможно какой-то модуль или сниппеты в теме негативно сказываются на данной функции.

  • Евгений   21.08.2018

    привет. у меня вопрос. почему кого ты переходишь на страницу товара, кнопка купить не рабочая. как сделать так что бы она была рабочая?

  • Tod   22.08.2018

    Евгений, вы уверены что товар есть в наличии, т.е. доступен? нужно тестить — ставить базовую тему, отключать модули и смотреть что конкретно вызывает проблему.

Оставить комментарий


Блог Wordpress Inside поможет вам научиться работать в вордпресс, закрепить и расширить имеющиеся знания. Плагины и шаблоны, разные хаки и функции wp, оптимизация и безопасность системы – все это и намного больше вы сможете найти на страницах нашего проекта!

Если хотите быстро и оперативно получать последние новости и статьи, то рекомендуем подписаться на обновления блога:

Поиск:
Последние посты
Лучшее в категории

Облако тегов
Скажи свое мнение!

В чем основные плюсы Wordpress?

Посмотреть результаты

Загрузка ... Загрузка ...
Друзья проекта
Последние новости