Ответы пользователя по тегу PHP
  • Изменение типа цены в зависимости от общей суммы корзины Woocommerce?

    @vanechka_ivan Автор вопроса
    На просторах интернета я нашел код который меняет цену товара на фиксированную без каких-либо условий.
    И вышло что-то на подобии этого:
    // Adding a wholesale price for items
    add_action( 'woocommerce_before_calculate_totals', 'add_custom_price', 20, 1);
    function add_custom_price( $cart ) {
        // This is necessary for WC 3.0+
        if ( is_admin() && ! defined( 'DOING_AJAX' ) )
            return;
        // Avoiding hook repetition (when using price calculations for example)
        if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
            return;
    
       // Get order subtotal
        $order_subtotal = WC()->cart->get_cart_subtotal();
       
        if ( $order_subtotal >= 2000 ) {
            foreach ( $cart->get_cart() as $item ) {
           // Значение set_price нужно будет заменить на id кастомной цены, если всё заработает
            $item['data']->set_price( 150.6 );
            }
        }
    }

    Тут для проверки роботоспосоности я просто изменяю цену товаров к корзине на фиксированную.

    Но при сохранении functions.php с этим кодом, сайт выдаёт ошибку при попытке добвления товара к корзину. Это происходит если я сравниваю подытог корзины с нужной мне суммой (при условии 1 == 1 всё работает). Также я не уверен что правильно получаю значение $order_subtotal.
    Даже при условии что код заработает как должет, будет ли присваиваться определённому товару конкретно его кастомная цена.

    UPD:
    Я начал проверять значение $order_subtotal через echo, но мне постоянно выдавало что оно равно 0 (нуль или ноль?). Не понимая что присходит я немного впал в отчаянне. Но. НО. После я заметил что в add_action написано woocommerce_before_calculate_totals. Хахахах. Всё было так просто. Там написано before. Это BEFORE. Т.е до подсчёта суммы. Лёгкими нажатиями своими пальчиками я заменил этот никчёмный "before" на нужный мне "after". И боги, оно заработало. Я начал видеть правильный мне подытог корзины.
    После я понял что если получать нужное мне значение через использывание get_cart_subtotal(), то я получаю сумму в виде строки со знаком валюты, а если использывать get_subtotal() мы получаем уже тип float, который можно использывать для конструкции if.
    Сейчас код имеет такой вид:
    // Adding a wholesale price for items
    add_action( 'woocommerce_after_calculate_totals', 'add_custom_price', 20, 1);
    function add_custom_price( $cart ) {
        // This is necessary for WC 3.0+
        if ( is_admin() && ! defined( 'DOING_AJAX' ) )
            return;
        // Avoiding hook repetition (when using price calculations for example)
        if ( did_action( 'woocommerce_after_calculate_totals' ) >= 2 )
            return;
    
        if ( WC()->cart->get_subtotal() >= 2000 ) {
            foreach ( $cart->get_cart() as $item ) {
            $item['data']->set_price( 150.6 );
            }
        }
    }


    P.S Пока редактировал текст заметил что когда подытог становится больше чем нужно (т.е условие выполняется) и товар преобретает нужную цену, конечый итог считает по старой цене. Буду думать дальше
    P.S 2 Я понял почему так происходит. Я задаю условие при котором цена товара задаётся уже после подсчёта суммы корзины и поэтому он считает по стандартному прайсу.

    UPS 2
    Дыыыы. Оно работает так как надо. Так как хотел того именно я.
    Код:
    // Adding a wholesale price for items
    add_action( 'woocommerce_after_calculate_totals', 'add_custom_price', 20, 1);
    function add_custom_price( $cart ) {
        // This is necessary for WC 3.0+
        if ( is_admin() && ! defined( 'DOING_AJAX' ) )
            return;
        // Avoiding hook repetition (when using price calculations for example)
        if ( did_action( 'woocommerce_after_calculate_totals' ) >= 2 )
            return;
        // Adding a custom price for items
        if ( WC()->cart->get_subtotal() >= 2000 ) {
            foreach ( $cart->get_cart() as $item ) {
            $item['data']->set_price( 150.6 );
            }
        }
        // Recount cart total
        WC()->cart->calculate_totals();
        // Wrong minimum amount protection
        if ( WC()->cart->get_subtotal() < 2000 ) {
            foreach ( $cart->get_cart() as $item ) {
            $regular_price = $item['data']->get_regular_price();
            $item['data']->set_price( $regular_price );
            }
        }
        // Recount cart total
        WC()->cart->calculate_totals();
    }


    А теперь по порядку. Во первых я не знал как пересчитать итоговую стоимость корзины с изменёнными ценами. у мена была идея которой я придерживался. Уже и не хочу думать как я бы это сделал, потому что уже голова болит от этого. Но суть именно в том как я начал это делать. Я добавил переменную $ca = WC()->cart->calculate_totals(). В попытках проверить не виснит ли сайт от такой логики при перезагрузки я не увидил сообщение о том что "Возникла ошибка. Поробуйте в другой раз." (Это уже очень радовало). Я решил попробывать изменить количесто товара. И именно тут я заметил что корзина пересчитывает итогувую сумму по новой, заданной мной, цене. ОоОООООООО. Я перекрестился и сказал чпасибо себе за то что я такой классный. После я оставил только WC()->cart->calculate_totals(), что также работало исправно.
    Понимая что смена цены работает только в одну сторону, я добавил вторую конструкцию if только с обратным условием. Фиксированную цену заменил на
    $regular_price = $item['data']->get_regular_price()
    и также добавил перерасчет суммы корзины после.
    Это моя лична маленькая победа над которой я очень горжусь, ведь до этого момента я не имел дело с php от слова вообще. Осталось только добавить оптовую цену, указать её в моём мальком коде и всё. На этом мои мучения закончены.
    Ответ написан
    1 комментарий