Reputation: 8647
I'm writing a quick-and-dirty module to restrict shipping methods based on products in the cart. For example, if the customer adds food, I only want overnight shipping methods to be selected. Some of the commercial extensions are just overkill and have way more functionality that I need.
Each product will have a dropdown attribute called "Shipping Class". The admin will be able to create these Shipping Classes in the backend. They will give it a name and choose which methods are allowed.
When it comes time to get shipping quotes, we'll only show allowed methods based on the Shipping Class.
My main question is: how can I retrieve a list of all the shipping methods for the admin to select from when creating these shipping classes?
And as a secondary question, does it make sense to do the filtering of allowed methods inside of Mage_Sales_Model_Quote_Address::requestShippingRates? (I will be overriding this method of course)
EDIT:
Thanks to @BrianVPS, I was able to come up with the code below. It displays all individual methods from the carriers using optgroups. Works great with multiselect! I don't think it checks if the methods are actually enabled though.
public function getAllShippingMethods()
{
$methods = Mage::getSingleton('shipping/config')->getActiveCarriers();
$options = array();
foreach($methods as $_ccode => $_carrier)
{
$_methodOptions = array();
if($_methods = $_carrier->getAllowedMethods())
{
foreach($_methods as $_mcode => $_method)
{
$_code = $_ccode . '_' . $_mcode;
$_methodOptions[] = array('value' => $_code, 'label' => $_method);
}
if(!$_title = Mage::getStoreConfig("carriers/$_ccode/title"))
$_title = $_ccode;
$options[] = array('value' => $_methodOptions, 'label' => $_title);
}
}
return $options;
}
Upvotes: 17
Views: 36926
Reputation: 2355
I've created a function for this out of the answers already provided. This creates an option group of all the shipping methods:
function getShippingMethods($_methods, $fieldId, $fieldName, $fieldClass){
$_shippingHtml = '<select name="' . $fieldName . '" id="' . $fieldId . '" class="' . $fieldClass . '">';
foreach($_methods as $_carrierCode => $_carrier){
if($_method = $_carrier->getAllowedMethods()) {
if(!$_title = Mage::getStoreConfig('carriers/' . $_carrierCode . ' /title')) {
$_title = $_carrierCode;
}
$_shippingHtml .= '<optgroup label="' . $_title . '">';
foreach($_method as $_mcode => $_m){
$_code = $_carrierCode . '_' . $_mcode;
$_shippingHtml .= '<option value="' . $_code . '">' . $_m . '</option>';
}
$_shippingHtml .= '</optgroup>';
}
}
$_shippingHtml .= '</select>';
return $_shippingHtml;
}
The $_methods
argument is an object from Magento:
$_methods = Mage::getSingleton('shipping/config')->getActiveCarriers();
So, we can call the function and pass the $_methods
object to it as follows:
<?php echo getShippingMethods($_methods, 'shipping_method', 'shipping_method', 'shipping'); ?>
Hope that helps someone else.
Upvotes: 4
Reputation: 21851
Taking @BrianVPS's answer, I'm using the code segment below (with structure shown) to help in my situation, where I wanted a simple human label from the shipping code.
$methods = Mage::getSingleton('shipping/config')->getActiveCarriers();
$shipping = array();
foreach($methods as $_ccode => $_carrier) {
if($_methods = $_carrier->getAllowedMethods()) {
if(!$_title = Mage::getStoreConfig("carriers/$_ccode/title"))
$_title = $_ccode;
foreach($_methods as $_mcode => $_method) {
$_code = $_ccode . '_' . $_mcode;
$shipping[$_code]=array('title' => $_method,'carrier' => $_title);
}
}
}
echo "\n";print_r($shipping);
/*
[flatrate_flatrate] => Array
[title] => Will-call
[carrier] => Pickup At Ca Cycleworks
[freeshipping_freeshipping] => Array
[title] => Economy
[carrier] => Free Ground Shipping
[ups_11] => Array
[title] => UPS Standard
[carrier] => United Parcel Service
[ups_12] => Array
[title] => UPS Three-Day Select
[carrier] => United Parcel Service
[ups_54] => Array
[title] => UPS Worldwide Express Plus
[carrier] => United Parcel Service
[ups_65] => Array
[title] => UPS Saver
[carrier] => United Parcel Service
[ups_01] => Array
[title] => UPS Next Day Air
[carrier] => United Parcel Service
[ups_02] => Array
[title] => UPS Second Day Air
[carrier] => United Parcel Service
[ups_03] => Array
[title] => UPS Ground
[carrier] => United Parcel Service
[ups_07] => Array
[title] => UPS Worldwide Express
[carrier] => United Parcel Service
[ups_08] => Array
[title] => UPS Worldwide Expedited
[carrier] => United Parcel Service
[customshippingrate_customshippingrate] => Array
[title] => Custom Shipping Rate
[carrier] => Custom Shipping Rate
*/
Upvotes: 10
Reputation: 2927
Here is a block of code I have in a source_model for a shipping extension I wrote. Hopefully this is what you're looking for.
...as for your second question, not sure....
public function toOptionArray($isMultiSelect = false)
{
$methods = Mage::getSingleton('shipping/config')->getActiveCarriers();
$options = array();
foreach($methods as $_code => $_method)
{
if(!$_title = Mage::getStoreConfig("carriers/$_code/title"))
$_title = $_code;
$options[] = array('value' => $_code, 'label' => $_title . " ($_code)");
}
if($isMultiSelect)
{
array_unshift($options, array('value'=>'', 'label'=> Mage::helper('adminhtml')->__('--Please Select--')));
}
return $options;
}
Upvotes: 24