Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Способ доставки

Способ доставки — класс, наследующий WC_Shipping_Method. Его главный метод calculate_shipping() получает содержимое корзины с адресом и сообщает цену. Способы привязаны к зонам доставки: зона — набор стран или регионов со своим списком способов и цен.

Зоны в панели

Откройте «WooCommerce → Настройки → Доставка». Создайте зону «Германия» с регионом «Германия» — в неё мы добавим свой способ. Покупателю показываются способы той зоны, под которую подходит его адрес.

Класс способа

Создайте файл includes/class-acme-shipping.php:

// wp-content/plugins/acme-shop/includes/class-acme-shipping.php
class Acme_Shipping extends WC_Shipping_Method
{
    public function __construct($instanceId = 0)
    {
        $this->id = 'acme_courier';
        $this->instance_id = absint($instanceId);
        $this->method_title = 'Курьер Acme';
        $this->method_description = 'Доставка собственным курьером.';
        $this->supports = ['shipping-zones', 'instance-settings'];
 
        $this->instance_form_fields = [
            'title' => ['title' => 'Название', 'type' => 'text', 'default' => 'Курьер'],
            'cost' => ['title' => 'Стоимость', 'type' => 'price', 'default' => '5'],
        ];
 
        $this->title = $this->get_option('title');
    }
 
    public function calculate_shipping($package = []): void
    {
        $this->add_rate([
            'id' => $this->get_rate_id(),
            'label' => $this->title,
            'cost' => (float) $this->get_option('cost'),
        ]);
    }
}

Экземпляр — способ, добавленный в конкретную зону: у каждого свой номер и свои настройки из instance_form_fields. Метод add_rate() предлагает покупателю вариант с названием и ценой.

Регистрация

// wp-content/plugins/acme-shop/acme-shop.php
add_action('woocommerce_shipping_init', function () {
    require_once __DIR__ . '/includes/class-acme-shipping.php';
});
 
add_filter('woocommerce_shipping_methods', function (array $methods): array {
    $methods['acme_courier'] = 'Acme_Shipping';
 
    return $methods;
});

Класс подключается на хуке woocommerce_shipping_init — раньше базового класса ещё нет. Ключ массива совпадает с id способа. Теперь откройте зону «Германия», нажмите «Добавить способ доставки» и выберите «Курьер Acme». На странице корзины с немецким адресом появится вариант «Курьер — 5,00 €».

Расчёт по содержимому

Аргумент $package содержит товары и адрес. Посчитаем цену по весу:

// wp-content/plugins/acme-shop/includes/class-acme-shipping.php
public function calculate_shipping($package = []): void
{
    $weight = 0.0;
 
    foreach ($package['contents'] as $item) {
        $weight += (float) $item['data']->get_weight() * $item['quantity'];
    }
 
    $cost = (float) $this->get_option('cost') + max(0, $weight - 2) * 1.5;
 
    $this->add_rate([
        'id' => $this->get_rate_id(),
        'label' => $this->title,
        'cost' => $cost,
    ]);
}

До двух килограммов действует базовая цена, каждый следующий килограмм добавляет 1,50 €. Вес товара задают в редакторе на вкладке «Доставка».

Ключ $packageЧто в нём
contentsПозиции корзины, как в WC()->cart->get_cart()
contents_costСумма товаров
destinationАдрес: country, state, postcode, city

Если способ недоступен — например, для слишком тяжёлой посылки, — add_rate() просто не вызывают.

Изменить чужие цены

Стоимость любых способов меняют фильтром, без своего класса. Сделаем доставку бесплатной от 50 €:

// wp-content/plugins/acme-shop/includes/cart.php
add_filter('woocommerce_package_rates', function (array $rates, array $package): array {
    if ($package['contents_cost'] >= 50) {
        foreach ($rates as $rate) {
            $rate->set_cost(0);
        }
    }
 
    return $rates;
}, 10, 2);

Фильтр получает все варианты, найденные для посылки. Наберите корзину на 50 € — все способы доставки станут бесплатными. Фильтр работает и в блочной корзине.

Частая ошибка

Цену изменили в коде, а в корзине остаётся старая. WooCommerce запоминает варианты доставки в сессии покупателя и пересчитывает их, только когда изменились корзина или адрес. При отладке измените количество товара в корзине или включите «Режим отладки» в «WooCommerce → Настройки → Доставка → Параметры доставки» — он отключает это запоминание.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.