I have been playing with Magento for couple days, and trying to understand the code inside it. It looks quite complicate.. probably because I am not really familiar with its frameworks. Basically it is PHP, but since files and functions are breaking up, and I have hard time to read its documentation, I actually still stuck how to start with it… Here is my task: I want to add a shipping option when my item is a small item (so that I don’t have to send it as parcel and save some bucks for customer). I have already defined two shipping option: Hong Kong Post Air Parcel and Hong Kong Speed Post. Here is my solution:
First, I added a new Tablerate table to my database.
CREATE TABLE shipping_tablerate2 ( `pk` int(10) unsigned NOT NULL auto_increment, `website_id` int(11) NOT NULL default '0', `dest_country_id` varchar(4) NOT NULL default '0', `dest_region_id` int(10) NOT NULL default '0', `dest_zip` varchar(10) NOT NULL default '', `condition_name` varchar(20) NOT NULL default '', `condition_value` decimal(12,4) NOT NULL default '0.0000', `price` decimal(12,4) NOT NULL default '0.0000', `cost` decimal(12,4) NOT NULL default '0.0000', PRIMARY KEY (`pk`), UNIQUE KEY `dest_country` (`website_id`,`dest_country_id`,`dest_region_id`,`dest_zip`,`condition_name`,`condition_value`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Because I want to create seperate tablerate for each option, so I must add a new table to the database.
Ok next I need to add module for this tablerate. There are many ways, but I just duplicated from the original tablerate module, and not sure if this is a correcy way.
The original module are located at:
app\code\core\Mage\Shipping\Model\Carrier\Tablerate.php
app\code\core\Mage\Shipping\Model\Mysql4\Carrier\Tablerate.php
app\code\core\Mage\Shipping\Model\Mysql4\Carrier\Tablerate\Collection.php
\app\code\core\Mage\Adminhtml\Model\System\Config\Backend\Shipping\Tablerate.php
\app\code\core\Mage\Adminhtml\Model\System\Config\Source\Shipping\Tablerate.php
and my module files are located at:
\app\code\core\Mage\Shipping\Model\Carrier\Tablerate2.php
\app\code\core\Mage\Shipping\Model\Mysql4\Carrier\Tablerate2.php
\app\code\core\Mage\Shipping\Model\Mysql4\Carrier\Tablerate2\Collection.php
\app\code\core\Mage\Adminhtml\Model\System\Config\Backend\Shipping\Tablerate2.php
\app\code\core\Mage\Adminhtml\Model\System\Config\Source\Shipping\Tablerate2.php
Both module files are basically the same, except I changed all “tablerate” to “tablerate2” inside each files. (so they will access the correct database table)
We also need to edit these files, but I am not going to go through this much:
\app\code\core\Mage\Shipping\etc\config.xml
\app\code\core\Mage\Shipping\etc\system.xml
So now, my products have an attribute which I defined in my admin panel called “small_item”, and it is a YesNo Option. I went through many sites and forum, but couldn’t really find what the value YesNo Attribute is, but I assume it is usually “Yes”, “No” or 1, 0. Furthermore, I am not really sure what is the correct way to retrieve the attribute… Finally I found a function getData(attribute_name), and it seems working for me.
Ok, once again, my task is I want to add a new table rate method for shipping small item that if the product attribute of “small_item” has value “yes”.
The file I edited is:
\app\code\core\Mage\Shipping\Model\Carrier\Tablerate2.php
I added a new function at the end of the file:
protected function checkSmallPacket($request) { $items = $request->getAllItems(); foreach ($items as $item) { //get each item from the shopping cart $_product=$item->getProduct(); $_product->load($_product->getId()); // load attribute for the product if ($_product->getData('small_item') == "0") // so if I found any attribute is "0"(No), return false; //then return false because there is a item not valid for this shipping method } return true; // all item valid for this shipping method }
I also modified the collectRate function:
public function collectRates(Mage_Shipping_Model_Rate_Request $request) { if (!$this->getConfigFlag('active')) { return false; } if (!$request->getConditionName()) { $request->setConditionName($this->getConfigData('condition_name') ? $this->getConfigData('condition_name') : $this->_default_condition_name); } $result = Mage::getModel('shipping/rate_result'); $rate = $this->getRate($request); $smallShippingOk = $this->checkSmallPacket($request); // Check if all item ok for small packet shipping if (!empty($rate) && $rate['price'] >= 0 && $smallShippingOk) { // Add Condition $method = Mage::getModel('shipping/rate_result_method'); $method->setCarrier('tablerate3'); $method->setCarrierTitle($this->getConfigData('title')); $method->setMethod('bestway'); $method->setMethodTitle($this->getConfigData('name')); $shippingPrice = $this->getFinalPriceWithHandlingFee($rate['price']); $method->setPrice($shippingPrice); $method->setCost($rate['cost']); $result->append($method); } return $result; }
$_product->getData(‘small_item’) actually return “0” or “1” (not integer, but string???), but I guess it is good enough for my task. I am sure there is a better way to do this, but can someone tell me? This module actually working well, but I haven’t fully tested it yet.
Dear Sir,
Can you let us know how to create a new Tablerate table to my database ?
Regards,
Lawrence
I am not sure if the Tablerate table structure is still same in the newer version of Magento, but to create a new Tablerate table to your database, usually can be done with any SQL clients, or most likely phpMyAdmin if your server has phpMyAdmin installed.
Sunny