Add new shipping method to Woocommerce programmatically

I’m trying to add a new shipping method to my Woocommerce suite.

Basically I’m trying to apply two different Shipping rates to an order depending on their user role. I’m using Flat Rate as one of them, but need a custom one made.

Read More

I have tried the the shipping api to create a new class but nothing seems to shows up.

<?php namespace MySite;

use WC_Shipping_Method;

    function your_shipping_method_init() {
        if ( ! class_exists( 'CustomShipping' ) ) {

            class CustomShipping extends WC_Shipping_Method {
                /**
                 * Constructor for your shipping class
                 *
                 * @access public
                 * @return void
                 */
                public function __construct() {
                    $this->id                 = 'your_shipping_method'; // Id for your shipping method. Should be uunique.
                    $this->method_title       = __( 'Your Shipping Method' );  // Title shown in admin
                    $this->method_description = __( 'Description of your shipping method' ); // Description shown in admin

                    $this->enabled            = "yes"; // This can be added as an setting but for this example its forced enabled
                    $this->title              = "My Shipping Method"; // This can be added as an setting but for this example its forced.

                    $this->init();
                }

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

                /**
                 * calculate_shipping function.
                 *
                 * @access public
                 * @param mixed $package
                 * @return void
                 */
                public function calculate_shipping( $package ) {
                    $rate = array(
                        'id' => $this->id,
                        'label' => $this->title,
                        'cost' => '10.99',
                        'calc_tax' => 'per_item'
                    );

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

    add_action( 'woocommerce_shipping_init', 'your_shipping_method_init' );

    function add_your_shipping_method( $methods ) {
        $methods[] = 'CustomShipping';
        return $methods;
    }

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

I use Composer to load my classes.

Aren’t I supposed to see the new option in the Woocommerce Shipping settings? Any guidance appreciated.

An alternative would be the intercept the session data and just change the shipping total and taxes there. That doesn’t seem to work however. Where can I find more data on where the shipping info comes from; where and when it’s called?

Related posts

2 comments

  1. There are two issues in your code. The first is that you are adding the action for woocommerce_shipping_init inside the function that you are attaching to it (so it’s never being called) and the the second is that you aren’t using the namespace you specified, namespace MySite.

    The first issue is easier to see if you check the indentation of your code, it’s all wrapped inside the init function.

    The second issue would be apparent in your logs with errors like the following once WooCommerce tries to load the class, which it isn’t doing due to the first issue.

    PHP Fatal error: Class ‘WC_Your_Shipping_Method’ not found in /wp-content/plugins/woocommerce/includes/class-wc-shipping.php on line 136

    PHP Warning: call_user_func_array() expects parameter 1 to be a valid callback, function ‘add_your_shipping_method’ not found or invalid function name in /wp-includes/plugin.php on line 213

    I removed your implementation code below but tested this on a dev site and it shows up as a shipping method in the WooCommerce settings.

    /*
      Plugin Name: WooCommerce Your Shipping Method
      Description: Test shipping method
      Version: 1.0
     */
    
    namespace MySite;
    
    use WC_Shipping_Method;
    
    function your_shipping_method_init() {
        if ( ! class_exists( 'WC_Your_Shipping_Method' ) ) {
    
            class WC_Your_Shipping_Method extends WC_Shipping_Method {
                // ... all your code for the implementation
            }
        }
    }  // <-- note that the function is closed before the add_action('woocommerce_shipping_init')
    
    // note "MySite" prepended to the attached function
    add_action( 'woocommerce_shipping_init', 'MySiteyour_shipping_method_init' );
    
    // note "MySite" prepended to the shipping method class name
    function add_your_shipping_method( $methods ) {
        $methods[] = 'MySiteWC_Your_Shipping_Method';
        return $methods;
    }
    
    // note "MySite" prepended to the attached function
    add_filter( 'woocommerce_shipping_methods', 'MySiteadd_your_shipping_method' );
    
  2. I’m not sure the precise issue with your code, but other shipping plugins do it like below, so I’d probably copy them:

    First put your method in another file classes/class-wc-your-shipping-method.php

    if ( ! class_exists( 'WC_Your_Shipping_Method' ) ) {
    
        class WC_Your_Shipping_Method extends WC_Shipping_Method {
            // your class stuff truncated for brevity
        }
    
    }
    

    then include the shipping class file from somewhere in your plugin:

    function so_32509983_init() {
        include_once( 'classes/class-wc-your-shipping-method.php' );
    }
    add_action( 'woocommerce_shipping_init', 'so_32509983_init' );
    

    finally tell WooCommerce to initialize your method as one of its active methods:

    function so_32509983_add_method( $methods ) {
        $methods[] = 'WC_Your_Shipping_Method';
        return $methods;
    }
    add_filter( 'woocommerce_shipping_methods', 'so_32509983_add_method' );
    

Comments are closed.