Shipping Method Dropdown and Set Default Shipping Method on Cart Page

In this tutorial we will see how to show a shipping method drop down in the cart totals and how to set a default shipping method in cart page.

There are many ways to do this but i am sharing with you the best method i know of.
Attached is screenshot of the module output

Shipping Dropdown Cart Page

Shipping Dropdown Cart Page

Attached is source code of this module
[dm]29[/dm]
Lets see step by step the explanation of this module. Also name of the module currently used is Excellence_Shipdrop

Step1: Adding dropdown to cart page

The first step in this module is to add a dropdown in place of the default magento shipping total display. To best way to do this in magento is as follows, in your config.xml file

<global>
<sales>
            <quote>
                <totals>
                    <shipping>
                    	<class>shipdrop/sales_quote_address_total_shipping</class>
                        <renderer>shipdrop/checkout_total_shipping</renderer>
                    </shipping>
                </totals>
            </quote>
        </sales>
</global>

the main thing to notice here is the value of <renderer> tag here, i have put here path to a block class. Using the <renderer> tag we can specify which block class magento should use to display the shipping cart totals. The code inside the block class is

<?php
class Excellence_Shipdrop_Block_Checkout_Total_Shipping extends Mage_Checkout_Block_Total_Default
{
	protected $_template = 'shipdrop/checkout/total/shipping.phtml';
}

The code is simple here, just specifies the path of the template file. In the template file shipdrop/checkout/total/shipping.phtml the code is

    <tr>
        <th colspan="2" style="<?php echo $this->getTotal()->getStyle() ?>" class="a-right">
           <?php
				$block = $this->getLayout()->createBlock('checkout/cart_shipping');
				$block->setTemplate('shipdrop/checkout/total/shipping/dropdown.phtml');
				echo $block->_toHtml(); 
			?>
        </th>
    </tr>

and in file shipdrop/checkout/total/shipping/dropdown.phtml the code is

<?php if (($_shippingRateGroups = $this->getEstimateRates())): ?>
<form id="co-shipping-method-form-drop" action="<?php echo $this->getUrl('checkout/cart/estimateUpdatePost') ?>">
	<select id='drop_estimate_method' name="estimate_method">
		<option value='-1'>Please Select Shipping Method</option>
		<?php 
		foreach ($_shippingRateGroups as $code => $_rates) { 
		$str = $this->getCarrierName($code);
		foreach ($_rates as $_rate){ 
			$str2 = $str . ' - ' . $_rate->getMethodTitle();
			
			$_excl = $this->getShippingPrice($_rate->getPrice(), $this->helper('tax')->displayShippingPriceIncludingTax());
			$_incl = $this->getShippingPrice($_rate->getPrice(), true);
			$str2 .= ' ['. $_excl;
			if ($this->helper('tax')->displayShippingBothPrices() && $_incl != $_excl) { 
				$str2 .= ' '. $this->__('Incl. Tax'); echo $_incl;
			}
			$str2 .= '] ';
		?>
		<option <?php if($_rate->getCode()===$this->getAddressShippingMethod()) echo ' selected="selected"' ?> value="<?php echo $this->htmlEscape($_rate->getCode()) ?>"><?php echo $str2;?></option>
		<?php } 
		} ?>
	</select>
</form>
<script type="text/javascript">
	document.observe("dom:loaded", function() {
		$('drop_estimate_method').observe('change',function(){
			if($('drop_estimate_method').getValue() == -1){
				alert('Please Select Shipping Method');
			}else{
				$('co-shipping-method-form-drop').submit();
			}
		});
	});
</script>
<?php endif; ?>

The above code generates the dropdown. Next we also need to make changes to the shipping totals collector class, because by default if shipping amount is zero no totals show up. So in the collector class we need to make a change to show totals even when shipping amount is zero. So the class which we mentioned in the config.xml file shipdrop/sales_quote_address_total_shipping we add this code

<?php
class Excellence_Shipdrop_Model_Sales_Quote_Address_Total_Shipping extends Mage_Sales_Model_Quote_Address_Total_Shipping{
	public function fetch(Mage_Sales_Model_Quote_Address $address)
	{
		$amount = $address->getShippingAmount();
		$title = Mage::helper('sales')->__('Shipping & Handling');
		if ($address->getShippingDescription()) {
			$title .= ' (' . $address->getShippingDescription() . ')';
		}
		$address->addTotal(array(
				'code' => $this->getCode(),
				'title' => $title,
				'value' => $address->getShippingAmount()
		));
		return $this;
	}
}

After doing this the shipping method dropdown should show up in totals. But now there is one more problem we need to fix, when a product is first added to shopping cart there no country select by user hence no shipping method will show up. So we need to add a code select the shipping country by default.

Step2: Select shipping country by default and shipping method

To do this we will add code in the events as below

<events>
    		<controller_action_predispatch_checkout_cart_index >
    			<observers>
    				<preIndex>
    					<class>shipdrop/observer</class>
                        <method>setShipping</method>
    				</preIndex>
    			</observers>
    		</controller_action_predispatch_checkout_cart_index>
    	</events>

So this event is execute before the indexAction() of CartController is called. In the setShipping() method we will put in this code to select a default country

<?php
class Excellence_Shipdrop_Model_Observer {
	public function setShipping($evt){
		$controller = $evt->getControllerAction();
		if(!Mage::getSingleton('checkout/type_onepage')->getQuote()->getShippingAddress()->getCountryId()  && Mage::getSingleton('checkout/type_onepage')->getQuote()->getItemsCount()){
			$country_id = 'IN';
			$region_id = false;
			$country = Mage::getModel('directory/country')->loadByCode($country_id);
			$regions = $country->getRegions();
			if(sizeof($regions) > 0){
				$region = $regions->getFirstItem();
				$region_id = $region->getId();
			}
			$customerSession=Mage::getSingleton("customer/session");
			if($customerSession->isLoggedIn()){
				$customerAddress=$customerSession->getCustomer()->getDefaultShippingAddress();
				if($customerAddress->getId()){
					$customerCountry=$customerAddress->getCountryId();
					$region_id = $customerAddress->getRegionId();
					$region = $customerAddress->getRegion();
					$quote = Mage::getSingleton('checkout/type_onepage')->getQuote();
					$shipping = $quote->getShippingAddress();
					$shipping->setCountryId($customerCountry);
					if($region_id){
						$shipping->setRegionId($region_id);
					}
					if($region){
						$shipping->setRegion($region);
					}
					$quote->save();
					$controller->getResponse()->setRedirect(Mage::getUrl('*/*/*',array('_current'=>true)));
				}else{
					$quote = Mage::getSingleton('checkout/type_onepage')->getQuote();
					$shipping = $quote->getShippingAddress();
					$shipping->setCountryId($country_id);
					if($region_id){
						$shipping->setRegionId($region_id);
					}
					$quote->save();
					$controller->getResponse()->setRedirect(Mage::getUrl('*/*/*',array('_current'=>true)));
				}
			}else{
				$quote = Mage::getSingleton('checkout/type_onepage')->getQuote();
				$shipping = $quote->getShippingAddress();
				$shipping->setCountryId($country_id);
				if($region_id){
					$shipping->setRegionId($region_id);
				}
				$quote->save();
				$controller->getResponse()->setRedirect(Mage::getUrl('*/*/*',array('_current'=>true)));
			}
		}

	}
}

The above code can also be easily extended to set a default shipping method as well. Just add a single line of code before $quote->save()

$quote->setShippingMethod('flatrate_flatrate');
$quote->save();
  • Pingback: abcphp.com()

  • Neha Ce15

    you are just awsome….right now i m using ur 2 or 3 modules…thats really helpful for me…thanks..

  • Shaktik

    Hi Manish
    I used your “shipping method drop down” Module.
    I want to make some changes in this module. I want this drop down available with each product in  checkout page. Each product can be shipped individually shipping method or with all. Prices should be reflect according to its shipping method.  I am attaching two images with it. First one is reference site where it is working with different framework website. Second image is on my localhost i want to make changes on it. Please guide me how to do it. My email id is “[email protected]

  • Hi Manish, i have a problem when I use the module. I must be connected to the site so that it appears. Otherwise, it doesn’t. Did you have that matter ?
    Thanks

  • Hello
    I am not able to download this module. it says archive is corrupted.

  • when logged in and logged out and again if we logged in and click on my cart link then dropdown is getting invisble and after refresh the dropdown is coming. I am unable to resolve it please help.

    • dream

      i have same problem did you find the solution for this.

      Thank you

  • dream

    Hi Manish

    when logged in and logged out and again if we logged in and click on my
    cart link then dropdown is getting invisble and after refresh the dropdown is coming. I am unable to resolve it please help.

    Thank you

  • Shylaja Remani

    Can we do this shipping method selection in product details page.?

  • Bob Davey

    I’m trying to install this module into v1.8.1 but although i can see the module is enabled in the backend I cannot get the drop down to show in the cart.
    Does anyone have it running in 1.8.1 or is it more likely my lack of understanding.
    Could someone please dumb it down & tell me where to install the files & which config.xml file to adjust. Thanks

  • Patrick Crosbie

    Hi Manish,

    This is great extension but I have one issue I cannot seem to solve, I am using a table rates, but it is only taking the first item in the table rate and applying to all. My rate is, regarding of the country etc (1 item $5) or (2 or more items $10). But when I add more than 1 item to the cart, the dropdown still show’s $5. Where have I gone wrong.

    Much appreciate all the help.

    Thanks

  • vikas rao

    Is there any way to display shipping charges per product in cart page or in product view page ?