Royal Mail Postage by Weight – Zend Framework Module

For a recent project I have had to calculate weight based shipping costs. Before I had this as a db table, but that became a mess to manage.

So I’ve created this small shipping calculator. It’s set to use KG in weight and prices inclusive of vat taken from the Royal Mail’s 2011 Prices.

Follows are the config ini file, the class and a basic usage.

[EUR]
prices[0.01] =1.79
prices[0.12] =1.94
prices[0.14] =2.15
prices[0.16] =2.32
prices[0.18] =2.54
prices[0.2] =2.63
prices[0.22] =2.75
prices[0.24] =2.87
prices[0.26] =2.99
prices[0.28] =3.08
prices[0.3] =3.14
prices[0.32] =3.8
prices[0.42] =4.46
prices[0.52] =5.12
prices[0.62] =5.78
prices[0.72] =6.44
prices[0.82] =7.1
prices[0.92] =7.76
prices[1] =7.76

above.start = 1.1
above.increment = 0.1
above.valuePerIncrement = 0.55

[ITL]
prices[0.01] =2.49
prices[0.12] =2.79
prices[0.14] =3.12
prices[0.16] =3.48
prices[0.18] =3.84
prices[0.2] =4.2
prices[0.22] =4.56
prices[0.24] =4.76
prices[0.26] =4.88
prices[0.28] =5
prices[0.3] =5.12
prices[0.32] =6.45
prices[0.42] =7.78
prices[0.52] =9.11
prices[0.62] =10.44
prices[0.72] =11.78
prices[0.82] =13.11
prices[0.92] =14.44
prices[1] =14.44

above.start = 1.1
above.increment = 0.1
above.valuePerIncrement = 0.66

[UK]
prices[0.1] =1.9
prices[0.25] =2.36
prices[0.5] =2.98
prices[0.75] =3.66
prices[1] =4.46
prices[1.25] =5.88
prices[1.5] =6.8
prices[1.75] =7.71
prices[2] =8.62
prices[4] =10.74

above.start = 6
above.increment = 2
above.valuePerIncrement = 3.66
<?php
class BinaryKitten_Shipping {
    private $_cfg;
    private $_curCfg;
    public function __construct($postalZone=null) {
        $this->_curCfg = $this->_cfg = new Zend_Config_Ini(APPLICATION_PATH .'/configs/postal.ini');
        if (isset($postalZone)) {
            $this->setPostalZone($postalZone);
        }
    }
    public function setPostalZone($postalZone)
    {
        if (self::validatePostalZone($postalZone)) {
            $this->_curCfg = $this->_cfg->get($postalZone, $this->_cfg);
        }

    }
    public static function validatePostalZone($postalZone)
    {
        return in_array(strtoupper($postalZone), array('UK','EUR','ITL'));
    }
    public function getPriceForWeight($weight)
    {
        $priceOut = -1;
        foreach($this->_curCfg->prices as $weightBoundary=>$price) {
            if ($weightBoundary < $weight) continue;
            if ($weightBoundary >= $weight) {
                $priceOut = $price;
                break;
            }
        }
        if ($priceOut == -1) {
            for($weightBoundary = (float)$this->_curCfg->above->start;$weightBoundary < $weight;$weightBoundary += $this->_curCfg->above->increment) {
                $price+=$this->_curCfg->above->valuePerIncrement;
            }

            $priceOut = $price;
            //try to calculate the difference
        }
        return (float)$priceOut;
    }
}
$prices = new BinaryKitten_Shipping();
$prices->setPostalZone('EUR');
$price = $prices->getPriceForWeight(5);

2 comments

  1. James Holden says:

    This is nice, reminds me of the shipping module I wrote for a shopping cart I wrote in around 2001. Now you just need to make it fit a list of items in the optimal combination of parcels :-)

  2. BinaryKitten says:

    I theory that wouldn’t be too difficult but beyond the remit of a price calculator.

Leave a Reply

Your email address will not be published. Required fields are marked *

*