Как добавить собственный рабочий метод доставки в WooCommerce 3

Я успешно создал новый способ доставки и дал ему поддержку зон доставки. Однако, когда я выбираю метод из раскрывающегося списка, чтобы добавить его в зону, он не отображается в «списке выбранных методов».

Я записал скринкаст gif для демонстрации:

screencast gif

Я не могу на всю жизнь понять, почему это не работает. Он отлично работает, если я выбираю один из стандартных методов (Скринкаст GIF)

Кто-нибудь знает, что здесь происходит и как заставить его работать?

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

if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {

    function request_a_shipping_quote_init() {
        if ( ! class_exists( 'WC_Request_Shipping_Quote_Method' ) ) {
            class WC_Request_Shipping_Quote_Method extends WC_Shipping_Method {
                /**
                 * Constructor for your shipping class
                 *
                 * @access public
                 * @return void
                 */
                public function __construct() {
                    $this->id                 = 'request_a_shipping_quote'; // Id for your shipping method. Should be uunique.
                    $this->method_title       = __( 'Request a Shipping Quote' );  // Title shown in admin
                    $this->method_description = __( 'Shipping method to be used where the exact shipping amount needs to be quoted' ); // Description shown in admin

                    $this->title = "Request a Shipping Quote"; // This can be added as an setting but for this example its forced.

                    $this->supports = array(
                        'shipping-zones'
                    );

                    $this->init();
                }

                /**
                 * Init your settings
                 *
                 * @access public
                 * @return void
                 */
                function init() {
                    // Load the settings API
                    $this->init_form_fields(); // This is part of the settings API. Override the method to add your own settings
                    $this->init_settings(); // This is part of the settings API. Loads settings you previously init.

                    // Save settings in admin if you have any defined
                    add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
                }

                function init_form_fields() {

                    $this->form_fields = array(

                        'enabled' => array(
                            'title'       => __( 'Enable', 'dc_raq' ),
                            'type'        => 'checkbox',
                            'description' => __( 'Enable this shipping method.', 'dc_raq' ),
                            'default'     => 'yes'
                        ),

                        'title' => array(
                            'title'       => __( 'Title', 'dc_raq' ),
                            'type'        => 'text',
                            'description' => __( 'Title to be displayed on site', 'dc_raq' ),
                            'default'     => __( 'Request a Quote', 'dc_raq' )
                        ),

                    );

                }

                /**
                 * calculate_shipping function.
                 *
                 * @access public
                 *
                 * @param mixed $package
                 *
                 * @return void
                 */

                public function calculate_shipping( $packages = array() ) {
                    $rate = array(
                        'id'       => $this->id,
                        'label'    => $this->title,
                        'cost'     => '0.00',
                        'calc_tax' => 'per_item'
                    );

                    // Register the rate
                    $this->add_rate( $rate );
                }
            }
        }
    }

    add_action( 'woocommerce_shipping_init', 'request_a_shipping_quote_init' );

    function request_shipping_quote_shipping_method( $methods ) {
        $methods['request_shipping_quote_shipping_method'] = 'WC_Request_Shipping_Quote_Method';

        return $methods;
    }

    add_filter( 'woocommerce_shipping_methods', 'request_shipping_quote_shipping_method' );
}

person jhob101    schedule 18.07.2017    source источник
comment
Это больше не работает в woocommerce 3+, см. эту ветку поддержки без ответа: wordpress.org/support/topic/   -  person LoicTheAztec    schedule 24.07.2017
comment
Существует конфликт между основным методом WC_Shipping_Method calculate_shipping() и тем, который определен в вашем плагине кода… Это проблема, которую необходимо решить. Поскольку выдается эта ошибка: Строгие стандарты: объявление WC_Request_Shipping_Quote_Method::calculate_shipping() должно быть совместимо с WC_Shipping_Method::calculate_shipping($package = Array) в /www/wp-content/plugins. /request_shipping_quote_method.php в строке 18   -  person LoicTheAztec    schedule 25.07.2017
comment
@LoicTheAztec Есть успехи в этом?   -  person omukiguy    schedule 28.11.2017
comment
В конце концов мне пришлось отказаться от этого маршрута, так как я не мог заставить его работать. Вместо этого я изменил назначение метода доставки наложенным платежом, переименовав его в «Рассчитать доставку» вместе с некоторыми другими пользовательскими битами, чтобы заставить его работать. Не самое аккуратное решение, но оно отлично работает на производственной площадке. Я уверен, что есть решение, которое работает с нестандартными способами доставки, но я не мог заставить его работать за то время, которое у меня было.   -  person jhob101    schedule 28.11.2017


Ответы (6)


Ключ метода в «woocommerce_shipping_methods» должен соответствовать идентификатору метода доставки.

В вашем случае: вы должны изменить

function request_shipping_quote_shipping_method( $methods ) {
    $methods['request_shipping_quote_shipping_method'] = 'WC_Request_Shipping_Quote_Method';

    return $methods;
}

add_filter( 'woocommerce_shipping_methods', 'request_shipping_quote_shipping_method' );

To:

function request_shipping_quote_shipping_method( $methods ) {
    $methods['request_a_shipping_quote'] = 'WC_Request_Shipping_Quote_Method';

    return $methods;
}

add_filter( 'woocommerce_shipping_methods', 'request_shipping_quote_shipping_method' );
person lior r    schedule 19.08.2017
comment
Только что заметил этот ответ - это исправило! Большое спасибо за ответ, очень признателен - person jhob101; 23.09.2017

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

введите описание изображения здесь

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

function request_a_shipping_quote_init() {
    if ( ! class_exists( 'Imp_WC_Shipping_Local_Pickup' ) ) {

        class Imp_WC_Pickup_Shipping_Method extends WC_Shipping_Method {
            /**
             * Constructor.
             *
             * @param int $instance_id
             */
            public function __construct( $instance_id = 0 ) {
                $this->id           = 'imp_pickup_shipping_method';
                $this->instance_id  = absint( $instance_id );
                $this->method_title = __( "Самовывоз из точки выдачи ( MO г. Дзержинский )", 'imp' );
                $this->supports     = array(
                    'shipping-zones',
                    'instance-settings',
                    'instance-settings-modal',
                );
                $this->init();
            }

            /**
             * Initialize custom shiping method.
             */
            public function init() {

                // Load the settings.
                $this->init_form_fields();
                $this->init_settings();

                // Define user set variables
                $this->title = $this->get_option( 'title' );

                // Actions
                add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
            }

            /**
             * Calculate custom shipping method.
             *
             * @param array $package
             *
             * @return void
             */
            public function calculate_shipping( $package = array() ) {
                $this->add_rate( array(
                    'label'   => $this->title,
                    'package' => $package,
                ) );
            }

            /**
             * Init form fields.
             */
            public function init_form_fields() {
                $this->instance_form_fields = array(
                    'title' => array(
                        'title'       => __( 'Самовывоз из точки выдачи ( MO г. Дзержинский )', 'imp' ),
                        'type'        => 'text',
                        'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ),
                        'default'     => __( 'Самовывоз из точки выдачи ( MO г. Дзержинский )', 'imp' ),
                        'desc_tip'    => true,
                    ),
                );
            }
        }
    }
}
add_action( 'woocommerce_shipping_init', 'request_a_shipping_quote_init' );

function request_shipping_quote_shipping_method( $methods ) {
    $methods['imp_pickup_shipping_method'] = 'Imp_WC_Pickup_Shipping_Method';

    return $methods;
}
add_filter( 'woocommerce_shipping_methods', 'request_shipping_quote_shipping_method' );
person Oleg Apanovich    schedule 30.04.2018
comment
Это помогло мне заставить мой способ доставки работать. $instance_id отсутствовал в методе конструктора и не вызывал неожиданного поведения при удалении или обработке этого метода доставки. - person Miguel Garrido; 14.05.2020
comment
Это также помогло мне. Снова требовался instance_id. Я также не мог показать это, пока не установил опоры. - person Lightbulb1; 28.05.2020

Изменить эту строку

public function calculate_shipping( $package ) {

к этой линии

public function calculate_shipping( $package = array() ) {
person Alice    schedule 27.07.2017
comment
Спасибо за это. Я реализовал этот код, но он все еще не работает. Сайт в настоящее время удален, поэтому я не вижу, какие ошибки возникают, заставлю его работать локально и посмотрю, увижу ли я какие-либо ошибки. - person jhob101; 31.07.2017
comment
Поэтому, когда я добавляю $package = array(), теперь ошибка не возникает, но поведение остается прежним — способ доставки не добавляется в список способов доставки. - person jhob101; 03.08.2017
comment
какую ошибку вы получаете? bcoz теперь вам нужно проверить, как вы обрабатывали пакеты внутри вашей функции, bcoz теперь это массив пакетов - person Alice; 03.08.2017
comment
Задокументирована ли где-нибудь структура массива пакетов, чтобы я мог знать, как правильно ее реализовать? - person jhob101; 03.08.2017
comment
Можете ли вы показать мне код функции calculate_shipping()? - person Alice; 03.08.2017
comment
Это как в коде исходного вопроса, который я редактировал. Не зная структуры массива $packages, я не знаю, как ее изменить. - person jhob101; 07.08.2017

WC_Custom_Shipping_Method — это абстрактный класс, и вы пытаетесь изменить его унаследованный метод calculate_shipping, который не разрешен абстрактными классами.

Попробуйте сделать это так.

<?php

    if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {

function request_a_shipping_quote_init() {
    class Abs_Custom_Shipping extends WC_Shipping_Method{}
    if ( ! class_exists( 'WC_Request_Shipping_Quote_Method' ) ) {
        class WC_Request_Shipping_Quote_Method extends Abs_Custom_Shipping {
            /**
             * Constructor for your shipping class
             *
             * @access public
             * @return void
             */
            public function __construct() {
                $this->id                 = 'request_a_shipping_quote'; // Id for your shipping method. Should be uunique.
                $this->method_title       = __( 'Request a Shipping Quote' );  // Title shown in admin
                $this->method_description = __( 'Shipping method to be used where the exact shipping amount needs to be quoted' ); // Description shown in admin

                $this->title = "Request a Shipping Quote"; // This can be added as an setting but for this example its forced.

                $this->supports = array(
                    'shipping-zones'
                );

                $this->init();
            }

            /**
             * Init your settings
             *
             * @access public
             * @return void
             */
            function init() {
                // Load the settings API
                $this->init_form_fields(); // This is part of the settings API. Override the method to add your own settings
                $this->init_settings(); // This is part of the settings API. Loads settings you previously init.

                // Save settings in admin if you have any defined
                add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
            }

            function init_form_fields() {

                $this->form_fields = array(

                    'enabled' => array(
                        'title'       => __( 'Enable', 'dc_raq' ),
                        'type'        => 'checkbox',
                        'description' => __( 'Enable this shipping method.', 'dc_raq' ),
                        'default'     => 'yes'
                    ),

                    'title' => array(
                        'title'       => __( 'Title', 'dc_raq' ),
                        'type'        => 'text',
                        'description' => __( 'Title to be displayed on site', 'dc_raq' ),
                        'default'     => __( 'Request a Quote', 'dc_raq' )
                    ),

                );

            }

            /**
             * calculate_shipping function.
             *
             * @access public
             *
             * @param mixed $package
             *
             * @return void
             */

            public function calculate_shipping( $packages = array() ) {
                $rate = array(
                    'id'       => $this->id,
                    'label'    => $this->title,
                    'cost'     => '0.00',
                    'calc_tax' => 'per_item'
                );

                // Register the rate
                $this->add_rate( $rate );
            }
        }
    }
}

add_action( 'woocommerce_shipping_init', 'request_a_shipping_quote_init' );

function request_shipping_quote_shipping_method( $methods ) {
    $methods['request_shipping_quote_shipping_method'] = 'WC_Request_Shipping_Quote_Method';

    return $methods;
}

add_filter( 'woocommerce_shipping_methods', 'request_shipping_quote_shipping_method' );
}

(расширить метод доставки в дочерний класс, затем расширить дочерний класс в дочерний класс, где вы можете изменить метод calculate_shipping).

Надеюсь, это имеет смысл.

С уважением

person Biplav Subedi    schedule 17.04.2018

У меня была эта проблема, и она сводила меня с ума в течение нескольких дней, пока, просматривая код Woocommerce, чтобы понять, что происходит, я не обнаружил, что при настройке метода фильтра для woocommerce_shipping_methods мне нужно было сделать индекс записи что я добавлял в этот массив так же, как свойство ID в моем классе метода доставки. Как только я это сделал, он добавил способ доставки и правильно показал его для зоны. Раньше я добавлял запись в массив в методе фильтра без индекса, который отлично работает, если WC видит метод, поэтому он казался нормальным. Однако код, который сохраняет настройки, использует идентификатор в качестве индекса для определения способа доставки. Судя по другим комментариям, я бы предположил, что этот конкретный индекс был добавлен в версию 3 WC. Надеюсь, это поможет.

person Sarah Gray    schedule 09.06.2018

Если ваш способ доставки по-прежнему не работает, вы должны убедиться, что

  1. instance_id должен быть определен в конструкторе, как в этом фрагменте


    public function __construct($instance_id = 0)
       {
              $this->instance_id = absint($instance_id);
              // other lines follow
        }

  1. нет устаревших данных: удалите временные данные и данные клиентов (Настройки WooCommerce > Статус > Инструменты)
person Emanuele Cipolla    schedule 21.09.2019