How to add a custom working Shipping Method in Woo

2019-04-26 01:48发布

I have successfully created a new shipping method and given it support for shipping zones. However when I come to select the method from the dropdown to add it to the zone it does not appear in the 'selected methods list'.

I recorded a screencast gif to demonstrate:

screencast gif

I can't for the life of me figure out why it's not working. It works fine if I select one of the standard methods (Screencast GIF)

Anyone know what's going on here and how to get it to work?

Here's the code that I have from this official thread: Shipping Method 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' );
}

5条回答
smile是对你的礼貌
2楼-- · 2019-04-26 02:06

WC_Custom_Shipping_Method is an abstract class and you are trying to change its inherited method calculate_shipping which abstract classes don't allow.

Try doing it like this.

<?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' );
}

( extend the shipping method into a child class, then extend the child class into a grandchild class where you can modify the calculate_shipping method ).

Hope it makes sense.

Regards

查看更多
男人必须洒脱
3楼-- · 2019-04-26 02:14

I had this issue and it was driving me crazy for a few days until, while looking through the Woocommerce code to understand what was happening, I discovered that when setting up the filter method for the woocommerce_shipping_methods, I needed to make the index of the entry that I was adding to this array the same as the ID property in my shipping method class. Once I did this, it added the shipping method fine and it showed it correctly for the zone. Previously, I had been adding the entry to the array in the filter method with no index, which works fine as far as WC seeing the method which was why it seemed ok. However, the code that saves the settings, uses the ID as the index to identify the shipping method. From other comments, I would imagine that this specific index was added in WC version 3. Hope this helps.

查看更多
做个烂人
4楼-- · 2019-04-26 02:20

After I trying to use code in question and fix all errors that I found in comments to these post I still had some problems with it. For example I can't edit shipping method after even I successfully added it to shipping zone.

enter image description here

Finally I got desired code that working for me after edit standard free shipping woocoommerce method. Hope it will save time for someone.

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' );
查看更多
相关推荐>>
5楼-- · 2019-04-26 02:21

The method key on "woocommerce_shipping_methods" should match the shipping method id

In your case: You should change

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' );
查看更多
劳资没心,怎么记你
6楼-- · 2019-04-26 02:24

Change this line

public function calculate_shipping( $package ) {

to this line

public function calculate_shipping( $package = array() ) {

查看更多
登录 后发表回答