Sunday, January 06, 2019

Introduction

A shipping module applies a shipping cost to an order, based on some calculation method. Each shipping module requires a minimum of two files:

  1. A class file: /includes/modules/shipping/modulename.php
  2. A language file: /includes/languages/current_language/modules/shipping/modulename.php

The language file contains all the translatable language text for the module while the class file contains the module's processing portion. A shipping module can include one or more methods.

Shipping Class

The class defined in /includes/classes/shipping.php handles the loading of the shipping modules during Zen Cart storefront order-processing.

Anatomy of a Shipping Module

Class Names

A shipping method's filename (e.g. myshipping.php) is also used as its class name:

class myshipping extends base
{
  ...
}

Note: Since an order's shipping selection is stored as a string combining a shipping module's name plus an underscore (_) plus the shipping-method selected, a shipping module's name cannot include an underscore!

Class Variables

A shipping-module's class definition includes, at a minimum, the following publicly-available variables:

Variable Name Variable Type Variable Usage
code string Contains the unique "code" identifying this shipping-module; normally set to the module's class name.
enabled boolean Identifies whether (true) or not (false) the module is enabled for use during the current storefront checkout.
title string Identifies the title displayed for the shipping-module during the admin's Modules->Shipping processing. This variable is normally initialized during class construction to a language-file definition.
description string Identifies the description displayed for the shipping-module during the admin's Modules->Shipping processing. This variable is normally initialized during class construction to a language-file definition.
tax_class integer Identifies the tax_class_id associated with the tax to be applied to this shipping module's costs. If the value is 0, the shipping cost is untaxed.
tax_basis string When the shipping cost is taxed, identifies the basis for the tax computation: either Billing, Shipping or Store.

Class Methods

Constructor

A shipping-module's class constructor performs initialization of its class variables and determines whether the shipping module is enabled for the current order. Upon completion, the class variable enabled identifies whether (true) or not (false) the module is to be enabled for storefront processing.

class myshipping extends base
{
    public function __construct ()
    {
    }

    ...
}

quote

This function determines the quote (i.e. the shipping cost) for either all methods supported by the module or for the specified module sub-method, depending on the function's input value. That quote information is returned in the class variable quotes: an associative array containing the following fields:

Element Name Required Type Description
id Yes string Normally set to the shipping method's code, i.e. its class name.
module Yes string The title displayed for the shipping module.
methods Yes array A simple, i.e. numerically-indexed, array of associative arrays. See below for each entry's definition.
tax No float If the shipping cost is to be taxed, the value returned is the rate to be applied. For instance, if the shipping is to be taxed at 8.37% this value will be 8.37; this value is normally that returned by call to the function zen_get_tax_rate.
icon No string If an icon is associated with the shipping module, this value is set to contain an HTML img tag (usually generated by call to zen_image) that sources that icon.
error No string If an error results from the quote's generation, this field contains the error-message to be displayed.

Each element of the methods array contains the following fields (depending on the shipping module, there might be additional fields):

Element Name Type Description
id string A unique string (for the current shipping module) that identifies this "method".
title string A text string containing the title to display for the current method.
cost float The cost associated with the current shipping method.

Basic quote function processing is illustrated below.

class myshipping extends base
{
    ...
    public function quote ($method = '')
    {
        global $order;

        ...

        $this->quotes = array (
            'id' => $this->code,
            'module' => $this->title,
            'methods' => array (
                array (
                   'id' => $method_name,
                   'title' => $method_description,
                   'cost' => $method_cost
                ),
                ...
            ),
        );
        if ($this->tax_class > 0) {
            $this->quotes['tax'] = zen_get_tax_rate($this->tax_class, $order->delivery['country']['id'], $order->delivery['zone_id']);
        }
        if (zen_not_null($this->icon)) {
            $this->quotes['icon'] = zen_image($this->icon, $this->title);
        }
        return $this->quotes;
    }

    ...
}
General Quote (all methods)

When the quote function is called with an input $method value of '' (an empty string), the function returns an array containing quotes for all methods it provides. One methods array entry is provided for each method applicable to the current order.

This form of the function call is used by the Shipping Estimator and in the shipping-method selection provided by the checkout_shipping page's handling.

Specific Method

When the quote function is called with a non-blank value in the $method input, the function returns an array containing the quote for that specific method. In this case, the quote can return an error indication if the specified shipping method is not available for the order.

check

This function, called from admin-level Modules->Shipping processing, returns a boolean value indicating whether (true) or not (false) the shipping-module is currently installed.

class myshipping extends base
{
    ...

    public function check ()
    {
        global $db;
        if (!isset ($this->_check)) {
            $check_query = $db->Execute ("SELECT configuration_value FROM " . TABLE_CONFIGURATION . " WHERE configuration_key = 'MODULE_SHIPPING_MYSHIPPING_STATUS' LIMIT 1");
            $this->_check = !$check_query->EOF;
        }
        return $this->_check;
    }

    ...
}

install

This function, called from admin-level Modules->Shipping processing when the shipping module is initially installed, sets the module's configuration into the Zen Cart database. The example shows how to insert the common, required, configuration elements into the database for the myshipping shipping module. If your shipping method requires additional settings, add them here.

class myshipping extends base
{
    ...

    public function install () 
    {
        global $db;

        $db->Execute ("INSERT INTO " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) VALUES ('Enable Flat Shipping', 'MODULE_SHIPPING_MYSHIPPING_STATUS', 'True', 'Do you want to offer "my shipping" shipping?', '6', '0', 'zen_cfg_select_option(array(\'True\', \'False\'), ', now())");
        $db->Execute ("INSERT INTO " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) VALUES ('Shipping Cost', 'MODULE_SHIPPING_MYSHIPPING_COST', '5.00', 'The shipping cost for all orders using this shipping method.', '6', '0', now())");
        $db->Execute ("INSERT INTO " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, use_function, set_function, date_added) VALUES ('Tax Class', 'MODULE_SHIPPING_MYSHIPPING_TAX_CLASS', '0', 'Use the following tax class on the shipping fee.', '6', '0', 'zen_get_tax_class_title', 'zen_cfg_pull_down_tax_classes(', now())");
        $db->Execute ("INSERT INTO " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) VALUES ('Tax Basis', 'MODULE_SHIPPING_MYSHIPPING_TAX_BASIS', 'Shipping', 'On what basis is Shipping Tax calculated. Options are<br />Shipping - Based on customers Shipping Address<br />Billing Based on customers Billing address<br />Store - Based on Store address if Billing/Shipping Zone equals Store zone', '6', '0', 'zen_cfg_select_option(array(\'Shipping\', \'Billing\', \'Store\'), ', now())");
        $db->Execute ("INSERT INTO " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, use_function, set_function, date_added) VALUES ('Shipping Zone', 'MODULE_SHIPPING_MYSHIPPING_ZONE', '0', 'If a zone is selected, only enable this shipping method for that zone.', '6', '0', 'zen_get_zone_class_title', 'zen_cfg_pull_down_zone_classes(', now())");
        $db->Execute ("INSERT INTO " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) VALUES ('Sort Order', 'MODULE_SHIPPING_MYSHIPPING_SORT_ORDER', '0', 'Sort order of display.', '6', '0', now())");

        ...

    }

    ...

}

keys

This function, called during admin-level Modules->Shipping processing, returns the database configuration "keys" associated with this shipping module. The configuration values are listed for the shipping module in the order specified by the returned array.

class myshipping extends base
{
    ...

    public function keys () 
    {
        return array (
            'MODULE_SHIPPING_MYSHIPPING_STATUS', 
            'MODULE_SHIPPING_MYSHIPPING_COST', 
            'MODULE_SHIPPING_MYSHIPPING_TAX_CLASS', 
            'MODULE_SHIPPING_MYSHIPPING_TAX_BASIS', 
            'MODULE_SHIPPING_MYSHIPPING_ZONE', 
            'MODULE_SHIPPING_MYSHIPPING_SORT_ORDER'
        );
    }

    ...

}

remove

This function, called during admin-level Modules->Shipping processing to remove this shipping module, removes all database configuration keys associated with the shipping method.

class myshipping extends base
{
    ...

    public function remove () 
    {
        global $db;
        $db->Execute ("DELETE FROM " . TABLE_CONFIGURATION . " WHERE configuration_key LIKE 'MODULE\_SHIPPING\_MYSHIPPING\_%'");
    }

    ...

}

Standard Configuration Settings

These common settings should be provided by all shipping modules:

Configuration Name Configuration Value
MODULESHIPPINGMYSHIPPING_STATUS Set to either 'true' or 'false', identifies whether or not the module is currently enabled
MODULESHIPPINGMYSHIPPING_ZONE If a zone is selected via the dropdown, the shipping module is enabled only for that zone.
MODULESHIPPINGMYSHIPPING_TAX_CLASS If the shipping is to be taxed, identifies the Tax Class associated with that tax
MODULESHIPPINGMYSHIPPING_TAX_BASIS Choose the address-basis (usually one of Shipping, Billing or Store) from which the tax is calculated.
MODULESHIPPINGMYSHIPPING_SORT_ORDER Identifies the sort-order to be used when displaying the currently-enabled shipping modules.

Tips & Tricks

Procedurally, all configuration options for a shipping module names myshipping should be named MODULESHIPPINGMYSHIPPING_*, as should all language constants for the module, to ensure uniqueness of those constants.

Troubleshooting

Since the admin-level processing by Modules->Shipping loads all .php modules present in the /includes/modules/shipping folder, make sure that any backup files in that directory have the .php extension renamed to something like .php~ or errors will result during the admin loading.


Powered by Codex 1.1.0