Shipping Modules

Calculating the shipping cost for an order

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 identifier for this shipping-module; normally set to the module’s class name.
enabled bool Determines whether (true) or not (false) the module is enabled for use during the current storefront checkout.
title string Contains the title displayed for the shipping-module in both the Admin Modules > Shipping and the storefront shipping quote. This variable is normally initialized during class construction to a (shopfront) language-file definition in the shipping module, e.g. MODULE_SHIPPING_(module name)_TEXT_TITLE
description string A description of the module displayed only in the Admin, Modules > Shipping. This variable is normally initialized during class construction to a (shopfront) language-file definition in the shipping module, e.g. MODULE_SHIPPING_(module name)_TEXT_DESCRIPTION
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 each of the module’s available methods or for the specified module sub-method, depending on the function’s $method input value. If no quote(s) is/are available, regardless the value provided for the $method input, the shipping module sets its quotes property to either (bool)false or an empty array ([]) and returns that value. Otherwise, the quote information is returned in the class propertyquotes: an associative array containing the following fields:

Element Name Required Type Description
id Yes string Set to the shipping method’s class variable code, i.e. its class name.
module Yes string Set to the shipping module’s language file title, e.g. MODULE_SHIPPING_(module name)_TEXT_TITLE
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 Set to the shipping method’s class variable code, i.e. its class name.
title string A text string containing the method name, e.g. MODULE_SHIPPING_(module name)_TEXT_WAY This text string is appended to the shipping module title to identify multiple methods within the same shipping module that may produce several quotes.
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 = [
            'id' => $this->code,
            'module' => $this->title,
            'methods' => [
                [
                   '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 (!empty($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) and one or more quotes is available, 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-empty value in the $method input and the quote is available, the function returns an array containing the quote for that specific method.

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([\'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([\'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 [
            '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
MODULE_SHIPPING_MYSHIPPING_STATUS Set to either ’true’ or ‘false’, identifies whether or not the module is currently enabled
MODULE_SHIPPING_MYSHIPPING_ZONE If a zone is selected via the dropdown, the shipping module is enabled only for that zone.
MODULE_SHIPPING_MYSHIPPING_TAX_CLASS If the shipping is to be taxed, identifies the Tax Class associated with that tax
MODULE_SHIPPING_MYSHIPPING_TAX_BASIS Choose the address-basis (usually one of Shipping, Billing or Store) from which the tax is calculated.
MODULE_SHIPPING_MYSHIPPING_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 MODULE_SHIPPING_MYSHIPPING_*, 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 changed, e.g. .php~ or .php.old, or errors will result during the admin loading.




Still have questions? Use the Search box in the upper right, or try the full list of FAQs. If you can't find it there, head over to the Zen Cart support forum and ask there in the appropriate subforum. In your post, please include your Zen Cart and PHP versions, and a link to your site.

Is there an error or omission on this page? Please post to General Questions on the support forum. Or, if you'd like to open a pull request, just review the guidelines and get started. You can even PR right here.
Last modified October 3, 2023 by lat9 (7cfc196).