Shipping Modules in Magento: Part 2

Exclusive offer: get 50% off this eBook here
Magento 1.3: PHP Developer's Guide

Magento 1.3: PHP Developer's Guide — Save 50%

Design, develop, and deploy feature-rich Magento online stores with PHP coding

$23.99    $12.00
by Jamie Huskisson | January 2010 | MySQL Open Source PHP

Read Part One of Shipping Modules in Magento here.

Appearing in the administration

Once this has been done, the shipping method should appear in Shipping Methods under System->Configuration:

Magento 1.3: PHP Developer's Guide

Now, we will look at the most useful shipping module fields that are used when putting the shipping module together. These are fields with predefined names and types that have automatically processed the results that they output. Therefore, they require no additional coding in the adaptor module to take them on board; Magento performs these methods straight out of the box.

Free shipping

If we want to enable an automatic price-based amount for free shipping with our method, we can add in a field called free_shipping_enable and combine this with another field by the name of free_shipping_subtotal. When free_shipping_enable is set to Enabled by the Magento administrator, then Magento will automatically take free_shipping_subtotal into account and offer free shipping if the total amount is above the value of free_shipping_subtotal.

If this field is disabled, Magento will simply process using the default shipping calculation behavior of the module.

 

The fields are set up as follows, with sort_order and show_in_ values varying:

<free_shipping_enable translate="label">
<label>Free shipping with minimum order amount</label>
<frontend_type>select</frontend_type>
<source_model>adminhtml/system_config_source_enabledisable</
source_model>
<sort_order>21</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
</free_shipping_enable>
<free_shipping_subtotal translate="label">
<label>Minimum order amount for free shipping</label>
<frontend_type>text</frontend_type>
<sort_order>22</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
</free_shipping_subtotal>

Handling

Handling charges sometimes come into the equation and need to be added onto the overall transaction. Magento enables us to do this using the following source models to present what we want to achieve:

<handling_type translate="label">
<label>Calculate Handling Fee</label>
<frontend_type>select</frontend_type>
<source_model>shipping/source_handlingType</source_model>
<sort_order>10</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>0</show_in_store>
</handling_type>
<handling_action translate="label">
<label>Handling Applied</label>
<frontend_type>select</frontend_type>
<source_model>shipping/source_handlingAction</source_model>
<sort_order>11</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>0</show_in_store>
</handling_action>
<handling_fee translate="label">
<label>Handling fee</label>
<frontend_type>text</frontend_type>
<sort_order>12</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
</handling_fee>

Restricting a shipping method to certain countries

This will allow us to present the option to the administrator for filtering the shipping method to be only accessible to certain countries. In practice, this means that if we wanted to offer only one type of delivery to the United Kingdom, then we could do so simply by selecting United Kingdom from the multi-select field created by the following declaration.

The Magento administrator can choose the specific countries from the multiple select list. Only orders from those countries that we have created shipping methods for will be processed in the shipping module. This enables them to choose any number of countries for restricting this shipping method to .

sallowspecific translate="label">
<label>Ship to applicable countries</label>
<frontend_type>select</frontend_type>
<sort_order>90</sort_order>
<frontend_class>shipping-applicable-country</frontend_class>
<source_model>adminhtml/system_config_source_shipping_
allspecificcountries</source_model>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
</sallowspecific>
<specificcountry translate="label">
<label>Ship to Specific countries</label>
<frontend_type>multiselect</frontend_type>
<sort_order>91</sort_order>
<source_model>adminhtml/system_config_source_country</source_model>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
</specificcountry>
<showmethod translate="label">
<label>Show method if not applicable</label>
<frontend_type>select</frontend_type>
<sort_order>92</sort_order>
<source_model>adminhtml/system_config_source_yesno</source_model>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
</showmethod>

Using our template to create a shipping method

Now that we have our bare-bones shipping module, we continue with the creation of something that we can see an outcome from. From this we should be able to start to put together our own shipping module tailor-made for future needs.

The purpose of what we are going to build is going to be very simple: we're going to create a shipping module that meets the following parameters:

  • It has a handling fee, either per product or for the entire order
  • It can be limited to specific countries
  • It can set a simple flat-rate shipping cost, if 10 products or more are being ordered
  • It can set another simple flat-rate shipping cost, if 10 products or less are being ordered
  • All of the above can be configured via the Magento administration

Before progressing, we delete the previous shipping module from our installation to make sure that it does not interfere with what we'll be building. To do this, we go back to the Magento Downloader  and select Uninstall from the module's supporting dropdown before committing the changes.

The configuration files

This time, we'll go with the directory MagentoBook and the name FullShippingModule. For this, our /app/code/local/MagentoBook/ShippingModule/MagentoBook/FullShippingModule/etc/config.xml file will look like:

<?xml version="1.0"?>
<config>
<modules>
<MagentoBook_FullShippingModule>
<version>0.1.0</version>
<depends>
<Mage_Shipping />
</depends>
</MagentoBook_FullShippingModule>
</modules>

<global>
<models>
<FullShippingModule>
<class>MagentoBook_FullShippingModule_Model</class>
</FullShippingModule>
</models>

<resources>
<fullshippingmodule_setup>
<setup>
<module>MagentoBook_FullShippingModule</module>
</setup>
<connection>
<use>core_setup</use>
</connection>
</fullshippingmodule_setup>
</resources>
</global>
</config>

We turn on FullShippingModule, and allow it to be turned off/on from within the administration. Then, we create /app/etc/modules/MagentoBook_FullShippingModule.xml and place the following in it:

<?xml version="1.0"?>
<config>
<modules>
<MagentoBook_FullShippingModule>
<active>true</active>
<codePool>local</codePool>
</MagentoBook_FullShippingModule>
</modules>
</config>

Our adaptor

For those interested in cutting down on code, unnecessary comments have been removed (which were included in the previous adaptor in this article).

We place the following code in: /app/code/local/MagentoBook/FullShippingModule/Model/Carrier/FullBoneMethod.php

<?php
class MagentoBook_FullShippingModule_Model_Carrier_FullBoneMethod
extends Mage_Shipping_Model_Carrier_Abstract
{
protected $_code = 'fullshippingmodule';
public function collectRates(Mage_Shipping_Model_Rate_Request
$request)
{
if (!$this->getConfigData('active')) {
Mage::log('The '.$this->_code.' shipping method is not
active.');
return false;
}
$handling = $this->getConfigData('handling');
$result = Mage::getModel('shipping/rate_result');
$method = Mage::getModel('shipping/rate_result_method');
$items = Mage::getModel('checkout/session')->getQuote()-
>getAllItems();
if (count($items) >= $this->getConfigData('minimum_item_limit')) {
$code = $this->getConfigData('over_minimum_code');
$title = $this->getConfigData('over_minimum_title');
$price = $this->getConfigData('over_minimum_price');
}
else {
$code = $this->getConfigData('under_minimum_code');
$title = $this->getConfigData('under_minimum_title');
$price = $this->getConfigData('under_minimum_price');
}
$method->setCarrier($this->_code);
$method->setCarrierTitle($this->getConfigData('title'));
$method->setMethod($code);
$method->setMethodTitle($title);
$method->setPrice($price + $handling);
$result->append($method);
return $result;
}
}

In short, this will check whether there are more items in the cart than the pre-configured value of minimum_item_limit and then apply a rate if it is over the set limit. If under the limit, it applies another rate.

Magento 1.3: PHP Developer's Guide Design, develop, and deploy feature-rich Magento online stores with PHP coding
Published: January 2010
eBook Price: $23.99
Book Price: $39.99
See more
Select your format and quantity:

We'll go through the code in blocks, so that we can understand it better.

First we declare our module as an extended class of Mage_Shipping, to make sure Magento knows it as a shipping method.

<?php
class MagentoBook_FullShippingModule_Model_Carrier_FullBoneMethod
extends Mage_Shipping_Model_Carrier_Abstract
{
protected $_code = 'fullshippingmodule';

We declare our collectRates function, which is the standard function for Magento to call with the request for rates when processing through all available shipping methods to it when a user is at the shipping method stage of ordering.

 public function collectRates(Mage_Shipping_Model_Rate_Request
$request)
{

Here we'll use an active variable set in the backend, when the administrator wants to disable this shipping method. We will check if the active variable is set to true and if it is not, false will be returned, so that Magento does not process any further. We will then tell the module to write to Magento's debug log using the Mage::log function call to ensure that we're aware the module isn't being used when going through them at any point in our development process.

if (!$this->getConfigData('active')) {
Mage::log('The '.$this->_code.' shipping method is not
active.');
return false;
}

We get our handling fee configuration value for adding onto our shipping method price later on. This variable has been set in the administration of our module and we're getting it out of the database to be used dynamically.

$handling = $this->getConfigData('handling');

We make sure that our shipping method is declared to the system and that the result array is sent to the user of shipping methods, if we want to add any available methods.

In practice this means that we set our method ( if available), then add this method to the result. The result in total (after going through all shipping modules installed in the system) is then returned to the user for selection of the preferred shipping method.

We also want to get the total amount of items in the cart, as our module depends on it.

$result = Mage::getModel('shipping/rate_result');
$method = Mage::getModel('shipping/rate_result_method');
$items = Mage::getModel('checkout/session')->getQuote()
->getAllItems();

If the amount of items in the current order is more than or equal to the amount that the minimum_item_limit variable is set to, we want discounted rates. Otherwise, we get the standard rates, as there is no discount.

if (count($items) >= $this->getConfigData('minimum_item_limit')) {
$code = $this->getConfigData('over_minimum_code');
$title = $this->getConfigData('over_minimum_title');
$price = $this->getConfigData('over_minimum_price');
}
else {
$code = $this->getConfigData('under_minimum_code');
$title = $this->getConfigData('under_minimum_title');
$price = $this->getConfigData('under_minimum_price');
}

We now need to set the internal code Magento will refer to this shipping method as when setting up orders and invoices in the system. We will then set its title and price to also be presented in the system and to the user on the frontend who is awaiting presentation of available shipping methods to them.

 $method->setCarrier($this->_code);
$method->setCarrierTitle($this->getConfigData('title'));
$method->setMethod($code);
$method->setMethodTitle($title);
$method->setPrice($price + $handling);
$result->append($method);
return $result;
}
}

The administration configuration

First, we'll create the /app/code/local/MagentoBook/FullShippingModule/etc/system.xml file using the bare-bones template we put together earlier in this article. We start by changing our carrier label to Full Boned Shipping inc.

<fullshippingmodule translate="label" module="shipping">
<label>Full Boned Shipping inc.</label>

Then we add our text-based fields to the system.xml configuration file, front_end_type text as per the previous conventions that we used with the following labels and variable names:

Variable Name

Label

minimum_item_limit

Minimum item quantity (if over rate the over minimum rate is applied)

over_minimum_code

Over minimum shipping code

over_minimum_title

Over minimum title

over_minimum_price

Over minimum price

under_minimum_code

Under minimum shipping code

under_minimum_title

Under minimum title

under_minimum_price

Under minimum price

Here's a reminder of the format for the field tags and how they should be formatted:

active translate="label">
<label>Enabled</label>
<frontend_type>select</frontend_type>
<source_model>adminhtml/system_config_source_yesno</source_model>
<sort_order>1</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
</active>

We make sure to define our sort order as we proceed. As a reminder—the <sort_order>  <sort_order> tag pair is how the order in which the fields appear is controlled. From 1 being the field to appear first, the highest number appears last in sequence. After we have defined these fields, we add the handling fields and country restriction fields. Once this is done, we have completed our configuration.

Testing our newly built module

We go into the administration under System->Configuration and then to Shipping Methods. Our new shipping method Full Boned Shipping inc. appears at the bottom.

Magento 1.3: PHP Developer's Guide

We must be sure to fill out the values here in the module and save them. In the previous screenshot, we have a Standard Shipping method, as there are less than two products in the cart. It provides Over Two Products special offer! shipping option when the user has equal to or over that amount of products in their cart. The pricing of both options has been set to reflect that and a handling charge of 5 per order has been added, which is applied as per the base currency (Pounds in this case).

To test the frontend, we go to the store and place x amount of products into the cart (either below or above the minimum item quantity set in our module) and progress to shipping to check if the rates are output. If we see them, then it works successfully!

Code to allow our shipping module to meet our needs

Here we see some small pieces of code to use within our shipping modules to achieve what we set out to do, when we created the module for a Magento store.

To get all items in the cart, we use:

$items = Mage::getModel('checkout/session')->getQuote()-
>getAllItems();
foreach($items as $item) {
// process each item here
};

Within the items foreach loop, we get the quantity for each item that is currently in the cart (also a great way to advance the fullbonesmodule built above):

$item_quantity = $item->getQty();

We check if a product is virtual or not, so that we don't need to calculate shipping:

if($item->getProduct()->getTypeInstance()->isVirtual()){
// it's a virtual product
} else{
// it's not a virtual product
}

Summary

In this article we've learned:

  • How to set up a basic bare-bones shipping module template for use in the future development of shipping modules
  • How to use shipping module-specific fields to limit our shipping module usage to certain countries
  • How to set up a basic administration section for our shipping module to allow it to be configured by Magento store administrators
  • How to put together a shipping method that decides on the shipping rate by the amount of items in the cart
  • Some useful pieces of code to use in our own shipping modules, when putting them together
[ 1 | 2 ]

If you have read this article you may be interested to view :

Magento 1.3: PHP Developer's Guide Design, develop, and deploy feature-rich Magento online stores with PHP coding
Published: January 2010
eBook Price: $23.99
Book Price: $39.99
See more
Select your format and quantity:

About the Author :


Jamie Huskisson

A passionate 23-year old freelance developer from Nottingham, Jamie Huskisson has been working with Magento for the past two years since the very early Beta versions. His development client list features names such as the NHS, Volkswagen, and Nike building everything from web applications to e-commerce stores and small business sites. He also trains groups of developers and provides consulting on adopting open source technologies over closed systems for clients when required.

Books From Packt

AJAX and PHP: Building Modern Web Applications 2nd Edition
AJAX and PHP: Building Modern Web Applications 2nd Edition

jQuery 1.3 with PHP
jQuery 1.3 with PHP

WordPress MU 2.8: Beginner's Guide
WordPress MU 2.8: Beginner's Guide

WordPress 2.8 Theme Design
WordPress 2.8 Theme Design

Python Testing: Beginner's Guide
Python Testing: Beginner's Guide

Building Telephony Systems with OpenSIPS 1.6
Building Telephony Systems with OpenSIPS 1.6

Joomla! with Flash
Joomla! with Flash

Moodle 1.9 Teaching Techniques
Moodle 1.9 Teaching Techniques

No votes yet
Same Problem here by
Hello.. I have done eveerthing the way you have written above.but didn't see the option in shipping mehtod on front end....
Can't make it work on front end by
Hello. I did all you wrte above. Thank yu very much for this tutorial. I use Magento ver. 1.4.0.1 I don't see any new shipping when I order. Any idea ?

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
H
v
F
P
z
n
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software