Latest Entries »

If you are facing a problem like in magento admin you can’t save acl information for api / admin user, here is the solution :-

For Api User overwrite the constructor of the block Mage_Adminhtml_Block_Api_Tab_Rolesedit with following function :-

 public function __construct() {
        Mage_Adminhtml_Block_Widget_Form :: __construct();
		//parent::__construct();

        $rid = Mage::app()->getRequest()->getParam('rid', false);

        $resources = Mage::getModel('api/roles')->getResourcesList();

        $rules_set = Mage::getResourceModel('api/rules_collection')->getByRoles($rid)->load();

        $selrids = array();
        foreach ($rules_set->getItems() as $item) {
            //changed the code here..
            if (array_key_exists($item->getResource_id(), $resources) && $item->getPermission() == 'allow') {
                $resources[$item->getResource_id()]['checked'] = true;
                array_push($selrids, $item->getResource_id());
            }
        }

        $this->setSelectedResources($selrids);

        $this->setTemplate('api/rolesedit.phtml');
    }

In this post I will show you how to write a basic magento model to do AMD activities to a db table.

Under package “Mypackage” & module “Mymod” we will create model Test so that we can do AMD with table named “test”.

1.Here we first create a table test in db.

CREATE TABLE `test` (
`test_id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`name` VARCHAR( 25 ) NOT NULL
) ENGINE = MYISAM 

2.Create shell module Mymod under package Mypackage

//file:- /app/etc/modules/Mypackage_Mymod.xml

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

3.Write config.xml for Mymod module. Here we declate a handler for table test .
//file:-/app/code/local/Mypackage/Mymod/etc/config.xml

/
<?xml version="1.0"?>
<config>
    <modules>
        <Mypackage_Mymod>
            <version>0.1.0</version>
        </Mypackage_Mymod>
    </modules>
    <global>
        <models>
			<mymod>
				<!-- Init model for mymod module -->
				<class>Mypackage_Mymod_Model</class>
				<!-- Init db config handler for mymod models -->
				<resourceModel>mymod_mysql4</resourceModel>
			</mymod>
			
			<!-- declaring model vs db table relation -->
            <mymod_mysql4>
                <class>Mypackage_Mymod_Model_Mysql4</class>
				<!-- declate table test -->
                <entities>
                    <test>
                        <table>test</table>
                    </test>
                </entities>
				<!-- -/- -->
            </mymod_mysql4>
			<!-- -/- -->
        </models>
		
		
		<!-- Setup db read & write connection for Mymod module -->
		<resources>
			<!-- db write connection -->
			<mymod_write>
				<connection>
					<use>core_write</use>
				</connection>
			</mymod_write>
			<!-- db read connection -->
			<mymod_read>
				<connection>
					<use>core_read</use>
				</connection>
			</mymod_read>
		</resources>
		<!-- -/- -->
    </global>
</config>

4.Write model Test.php. Here we configure this model with the handler of table test.
file:-/app/code/local/Mypackage/Mymod/model/Test.php

<?php

class Mypackage_Mymod_Model_Test extends Mage_Core_Model_Abstract
{
	
	public function _construct()
    {
        parent::_construct();
        $this->_init('mymod/test');
    }
}

5.Create the resource model for model test.
file:-/app/code/local/Mypackage/Mymod/model/Mysql4/Test.php. here we also configure the primary key id of the table test.

<?php

class Mypackage_Mymod_Model_Mysql4_Test extends Mage_Core_Model_Mysql4_Abstract
{
    public function _construct()
    {    
        $this->_init('mymod/test', 'test_id');
    }
}

6.Create a collection class so that we can retrive data from table test.
file:-/local/Mypackage/Mymod/model/Mysql4/Test/Collection.php

<?php

class Mypackage_Mymod_Model_Mysql4_Test_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract
{
    public function _construct()
    {
        parent::_construct();
        $this->_init('Mymod/test');
    }
}

That’s it we are done. Now we can do AMD operation with table test with model test.

	$model = Mage::getModel('mymod/test')
		->setName('Asad Rahman')
		->save();

Also use the test collection model to retrive collection data from table test.

	$model = Mage::getModel('mymod/test')
	$data = $model->getCollection()->getData();
	print_r($data);
$productId = 10; 
$attributeName = 'my_attribute_name';

$product = Mage::getModel('catalog/product')->load($productId);
$attributes = $product->getAttributes();

$attributeValue = null;		
if(array_key_exists($attributeName , $attributes)){
	$attributesobj = $attributes["{$attributeName}"];
	$attributeValue = $attributesobj->getFrontend()->getValue($product);
}
echo $attributeValue; //attribute value for 'my_attribute_name'

Here is a code snippet exaple how you fetch all products by it’s attribute set name:-

//Fetch attribute set id by attribute set name
$attrSetName = 'my_custom_attribute';
$attributeSetId = Mage::getModel('eav/entity_attribute_set')
	->load($attrSetName, 'attribute_set_name')
	->getAttributeSetId();

//Load product model collecttion filtered by attribute set id
$products = Mage::getModel('catalog/product')
	->getCollection()
	->addAttributeToSelect('name')
	->addFieldToFilter('attribute_set_id', $attributeSetId);

//process your product collection as per your bussiness logic
$productsName = array();
foreach($products as $p){
	$productsName[] = $p->getData('name');
}
//return all products name with attribute set 'my_custom_attribute'
print_r($productsName); 

That’s it, have happy time with magento ๐Ÿ™‚ !!!

Magento date time

Are you using date-time functions (date(), time(),now(), etc) directly inside magento ??? Think twice man !!!

Even though time is set properly in you server or you set right timezone in your php.ini file, you might be surprised to see the result of the following code :-

//This time will not match your server time
$now = time();
echo date('m/d/y h:i:s', time());

This is because whatever settings you have in your php.ini, Magento reset timezone to ‘UTC’ in Mage_Core_Model_App.

File:- \app\code\core\Mage\Core\Model\App.php Line:-255

date_default_timezone_set(Mage_Core_Model_Locale::DEFAULT_TIMEZONE);

So, solution is set your targeted timezone in Admin->System->Configuration / General->Locale options and rather using date() function user the following code:-

$now = Mage::getModel('core/date')->timestamp(time());
echo date('m/d/y h:i:s', $now);

That’s it, have happy time with Magento ๐Ÿ™‚ .

Percentage off tier pricing in magento

Magento has an awesome feature for setting different tiered pricing for different quantity and also for different customer group. But sometimes you may feel this is problematic since you have to set a fixed price for tier items.

So, Lets make our hands dirty to extend this feature so that we can set a percentage which % amount will be deducted from the item price.

Step1

Magento keeps productโ€™s tier pricing information in product_entity_tier_price table. Fist lets create a new column โ€œtier_typeโ€ to keep track which type(Fixed / percentage) of tier pricing to be applied.

File:/app/etc/modules/Mypackage_Tierpricing.xml

<?xml version="1.0"?>
<config>
	<modules>

		<Mypackage_Tierpricing>
			<active>true</active>
			<codePool>local</codePool>
		</Mypackage_Tierpricing>

	</modules>
</config>

File:/app/code/local/Mypackage/Tierpricing/etc/config.xml

<?xml version="1.0"?>
<config>
    <modules>
        <Mypackage_Tierpricing>
            <version>0.1.0</version>
        </Mypackage_Tierpricing>
    </modules>
	<global>
        <resources>
            <tierpricing_setup>
                <setup>
                    <module>Mypackage_Tierpricing</module>
                </setup>
                <connection>
                    <use>core_setup</use>
                </connection>
            </tierpricing_setup>
            <tierpricing_write>
                <connection>
                    <use>core_write</use>
                </connection>
            </tierpricing_write>
            <tierpricing_read>
                <connection>
                    <use>core_read</use>
                </connection>
            </tierpricing_read>
        </resources>
    </global>
</config>

File: /app/code/local/Mypackage/Tierpricing/sql/tierpricing_setup/mysql4-install-0.1.0.php

<?php

	$installer = $this;
	$installer->startSetup();

	$installer->run(
		"ALTER TABLE {$this->getTable('catalog_product_entity_tier_price')}  ADD tier_type INT NOT NULL AFTER qty ; ");
	$installer->endSetup();

Step2

Lets change the product admin panel to save/update tier type (Fixed/percentage). We override the block Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Attribute_Backend_Tierprice so that it fetches the “tier_type”
from db.

File:-app/code/local/Mypackage/Catalog/Model/Product/Attribute/Backend/Tierprice.php


<?php

class Mypackage_Catalog_Model_Resource_Eav_Mysql4_Product_Attribute_Backend_Tierprice extends Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Attribute_Backend_Tierprice

{
    public function loadProductPrices($product, $attribute)
    {
		//add new column name to the sql
        $select = $this->_getReadAdapter()->select()
            ->from($this>getMainTable(), array(
                'website_id', 'all_groups', 'cust_group' => 'customer_group_id',
                'price_qty' => 'qty', 'price' => 'value', 'tier_type',
            ))
            ->where('entity_id=?', $product->getId())
            ->order('qty');
        if ($attribute->isScopeGlobal()) {
            $select->where('website_id=?', 0);
        }
        else {
            if ($storeId = $product->getStoreId()) {
                $select->where('website_id IN (?)', array(0, Mage::app()->getStore($storeId)->getWebsiteId()));
            }
        }
        return $this->_getReadAdapter()->fetchAll($select);
    }
}

?>

To save tier_type we to override the backend model Mage_Catalog_Model_Product_Attribute_Backend_Tierprice.

File:-app/code/local/Mypackage/Catalog/Model/Resource/Eav/Mysql4/Product/Attribute/Backend/Tierprice.php

<?php
class Mypackage_Catalog_Model_Product_Attribute_Backend_Tierprice extends Mage_Catalog_Model_Product_Attribute_Backend_Tierprice
{
    public function afterSave($object)
    {
        $this->_getResource()->deleteProductPrices($object, $this->getAttribute());
        $tierPrices = $object->getData($this->getAttribute()->getName());

        if (!is_array($tierPrices)) {
            return $this;
        }

        $prices = array();
        foreach ($tierPrices as $tierPrice) {
            if (empty($tierPrice['price_qty']) || !isset($tierPrice['price']) || !empty($tierPrice['delete'])) {
                continue;
            }

            $useForAllGroups = $tierPrice['cust_group'] == Mage_Customer_Model_Group::CUST_GROUP_ALL;
            $customerGroupId = !$useForAllGroups ? $tierPrice['cust_group'] : 0;
            $priceKey = join('-', array(
                $tierPrice['website_id'],
                intval($useForAllGroups),
                $customerGroupId,
                $tierPrice['price_qty']
            ));
			//Add new column "tier_type"
            $prices[$priceKey] = array(
                'website_id'        => $tierPrice['website_id'],
                'all_groups'        => intval($useForAllGroups),
                'customer_group_id' => $customerGroupId,
                'qty'               => $tierPrice['price_qty'],
                'value'             => $tierPrice['price'],
				'tier_type'			=> $tierPrice['tier_type'],
            );
        }

        if ($this->getAttribute()->getIsGlobal() == Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_WEBSITE) {
            if ($storeId = $object->getStoreId()) {
                $websites = array(Mage::app()->getStore($storeId)->getWebsite());
            }
            else {
                $websites = Mage::app()->getWebsites();
            }

            $baseCurrency   = Mage::app()->getBaseCurrencyCode();
            $rates          = $this->_getWebsiteRates();
            foreach ($websites as $website) {
                /* @var $website Mage_Core_Model_Website */
                if (!is_array($object->getWebsiteIds()) || !in_array($website->getId(), $object->getWebsiteIds())) {
                    continue;
                }
                if ($rates[$website->getId()]['code'] != $baseCurrency) {
                    foreach ($prices as $data) {
                        $priceKey = join('-', array(
                            $website->getId(),
                            $data['all_groups'],
                            $data['customer_group_id'],
                            $data['qty']
                        ));
                        if (!isset($prices[$priceKey])) {
                            $prices[$priceKey] = $data;
                            $prices[$priceKey]['website_id'] = $website->getId();
                            $prices[$priceKey]['value'] = $data['value'] * $rates[$website->getId()]['rate'];
                        }
                    }
                }
            }
        }

        foreach ($prices as $data) {
            $this->_getResource()->insertProductPrice($object, $data);
        }

        return $this;
    }
}

Change the admin phtml for tier pricing.
File:-/app/design/adminhtml/default/default/template/catalog/product/edit/price/tier.phtml

<?php
<?php $_htmlId      = $this->getElement()->getHtmlId() ?>
<?php $_htmlClass   = $this->getElement()->getClass() ?>
<?php $_htmlName    = $this->getElement()->getName() ?>
<?php $_readonly    = $this->getElement()->getReadonly() ?>
<?php $_multiWebsite= $this->isMultiWebsites(); ?>
<tr>
    <td class="label"><?php echo $this->getElement()->getLabel() ?></td>
</tr>
<tr>	
    <td colspan="10" class="grid tier">
    <table cellspacing="0" class="data border" id="tiers_table">
        <?php if ($_multiWebsite): ?>
        <col width="135" />
        <?php endif; ?>
        <col width="120" />
        <col width="60" />
        <col width="140"/>
        <col width="60" />
        <thead>
		
            <tr class="headings">
                <th <?php if (!$_multiWebsite): ?>style="display:none"<?php endif; ?>><?php echo Mage::helper('sales')->__('Website') ?></th>
                <th><?php echo Mage::helper('catalog')->__('Customer Group') ?></th>
                <th><?php echo Mage::helper('catalog')->__('Qty') ?></th>
				<!-- Added -->
				<th><?php echo Mage::helper('catalog')->__('Type') ?></th>
				<!-- -/- -->
                <th><?php echo $this->getPriceColumnHeader(Mage::helper('catalog')->__('Price')) ?></th>
                <th class="last"><?php echo Mage::helper('catalog')->__('Action') ?></th>
            </tr>
			
            <tr id="<?php echo $_htmlId ?>_add_template" class="template no-display">
				<!-- Website list -->
                <td <?php if (!$_multiWebsite): ?>style="display:none"<?php endif; ?>>
                <select disabled="no-template" class="<?php echo $_htmlClass ?> required-entry" name="<?php echo $_htmlName ?>[__index__][website_id]" id="tier_price_row___index___website">
                    <?php foreach ($this->getWebsites() as $_websiteId => $_info): ?>
                    <option value="<?php echo $_websiteId ?>"><?php echo $_info['name'] ?><?php if (!empty($_info['currency'])): ?> [<?php echo $_info['currency'] ?>]<?php endif; ?></option>
                    <?php endforeach ?>
                </select>
                </td>
				<!-- -/- -->
				
				<!-- Customer Group -->
                <td>
                <select disabled="no-template" class="<?php echo $_htmlClass ?> custgroup required-entry" name="<?php echo $_htmlName ?>[__index__][cust_group]" id="tier_price_row___index___cust_group">
                    <?php foreach ($this->getCustomerGroups() as $_groupId=>$_groupName): ?>
                    <option value="<?php echo $_groupId ?>"><?php echo htmlspecialchars($_groupName) ?></option>
                    <?php endforeach ?>
                </select>
                </td>
				<!-- -/- -->
				
				<!-- Qty -->
                <td class="nobr">
                    <input disabled="no-template" class="<?php echo $_htmlClass ?> qty required-entry validate-greater-than-zero" type="text" name="<?php echo $_htmlName ?>[__index__][price_qty]" value="'#{qty}'" /> <small class="nobr"><?php echo Mage::helper('catalog')->__('and above')?></small>
                </td>
				<!-- -/- -->
				
				<!-- Added type-->
				<td class="nobr">
				<select disabled="no-template" class="<?php echo $_htmlClass ?> tiertype required-entry" name="<?php echo $_htmlName ?>[__index__][tier_type]" id="tier_price_row___index___tier_type" >
					<option value="0">Fixed</option>
					<option value="1">% Off</option>
				</select>
                </td>
				<!-- -/- -->
				
				<!-- Price -->
                <td>
                    <input disabled="no-template" class="<?php echo $_htmlClass ?> required-entry validate-greater-than-zero" type="text" name="<?php echo $_htmlName ?>[__index__][price]" value="'#{price}'" />
                </td>
				<!-- -/- -->
				
				<!-- Button -->
                <td class="last"><input type="hidden" name="<?php echo $_htmlName ?>[__index__][delete]" class="delete" disabled="no-template" value="" /><button title="Delete Tier" class="scalable delete icon-btn delete-product-option" onclick="tierPriceControl.deleteItem(event);return false"><span>Delete</span></button></td>
				<!-- -/- -->
            </tr>
        </thead>
        <tfoot>
            <tr>
                <td <?php if (!$_multiWebsite): ?>style="display:none"<?php endif; ?>></td>
                <td colspan="5" class="a-right"><?php echo $this->getAddButtonHtml() ?></td>
            </tr>
        </tfoot>
        <tbody id="<?php echo $_htmlId ?>_container">
        </tbody>
    </table>

<script type="text/javascript">
//<![CDATA[
    var tierPriceControl = {
        template : new Template('<tr>' + $('<?php echo $_htmlId ?>_add_template').innerHTML.replace(/__index__/g, '#{index}').replace(/ disabled="?no-template"?/g, '').replace(/ disabled/g, '').replace(/="'([^']*)'"/g, '="$1"') + '</tr>'),
        itemsCount : 0,
        deleteButton: false,
        addItem  : function () {
            <?php if ($_readonly): ?>
            if (arguments.length < 4) {
                return;
            }
            <?php endif; ?>
            var data = {};
            data.website_id = 0;
            data.group = '<?php echo $this->getDefaultCustomerGroup() ?>';
            data.qty = '';
            data.price = '';
            data.index = this.itemsCount++;
            if(arguments.length == 5) {
                data.website_id = arguments[0];
                data.group      = arguments[1];
                data.qty        = arguments[2];
                data.price      = arguments[3];
				data.tier_type  = arguments[4];
            }
            Element.insert($('<?php echo $_htmlId ?>_container'), {'bottom':this.template.evaluate(data)});
            $('tier_price_row_'+data.index+'_cust_group').value = data.group;
            $('tier_price_row_'+data.index+'_website').value 	= data.website_id;
            $('tier_price_row_'+data.index+'_tier_type').value 	= data.tier_type;
            <?php if ($_readonly): ?>
            $('<?php echo $_htmlId ?>_container').select('input', 'select')
                .each(this.disableElement);
            $('<?php echo $_htmlId ?>_container').up('table').select('button')
                .each(this.disableElement);
            <?php endif; ?>
        },
        disableElement: function(elem) {
            elem.disabled = true
            elem.addClassName('disabled');
        },
        deleteItem : function(event) {
            var tr = Event.findElement(event, 'tr');
            if (tr) {
                Element.select(tr, '.delete').each(function(elem){elem.value='1'});
                Element.select(tr, ['input', 'select']).each(function(elem){elem.hide()});
                Element.hide(tr);
                Element.addClassName(tr, 'no-display template');
            }
        }
    }
    <?php foreach ($this->getValues() as $_item): ?>

    tierPriceControl.addItem('<?php echo $_item['website_id'] ?>', '<?php echo $_item['cust_group'] ?>', '<?php echo $_item['price_qty']*1 ?>','<?php echo sprintf('%.2f', $_item['price']) ?>','<?php echo $_item['tier_type'] ?>');
    <?php endforeach; ?>
    <?php if ($_readonly): ?>
        $('<?php echo $_htmlId ?>_container').up('table').select('button')
            .each(tierPriceControl.disableElement);
    <?php endif; ?>
//]]>
</script>
</td>
</tr>

Step 3

To change tier pricing we override the Mage_Catalog_Model_Product_Type_Price model’s getTierPrice method.

File:-/app/code/local/Mypackage/Catalog/Model/Product/Type/Price.php

<?php
class Mypackage_Catalog_Model_Product_Type_Price extends Mage_Catalog_Model_Product_Type_Price
{
	public function getTierPrice($qty=null, $product)
    {
        $allGroups = Mage_Customer_Model_Group::CUST_GROUP_ALL;
        $prices = $product->getData('tier_price');

        if (is_null($prices)) {
            if ($attribute = $product->getResource()->getAttribute('tier_price')) {
                $attribute->getBackend()->afterLoad($product);
                $prices = $product->getData('tier_price');
            }
        }
		
        if (is_null($prices) || !is_array($prices)) {
            if (!is_null($qty)) {
                return $product->getPrice();
            }
            return array(array(
                'price'         => $product->getPrice(),
                'website_price' => $product->getPrice(),
                'price_qty'     => 1,
                'cust_group'    => $allGroups,
            ));
        }

        $custGroup = $this->_getCustomerGroupId($product);
        if ($qty) {
            $prevQty = 1;
            $prevPrice = $product->getPrice();
            $prevGroup = $allGroups;
            foreach ($prices as $price) {
                if ($price['cust_group']!=$custGroup && $price['cust_group']!=$allGroups) {
                    // tier not for current customer group nor is for all groups
                    continue;
                }
                if ($qty < $price['price_qty']) {
                    // tier is higher than product qty
                    continue;
                }
                if ($price['price_qty'] < $prevQty) {
                    // higher tier qty already found
                    continue;
                }
                if ($price['price_qty'] == $prevQty && $prevGroup != $allGroups && $price['cust_group'] == $allGroups) {
                    // found tier qty is same as current tier qty but current tier group is ALL_GROUPS
                    continue;
                }

                $prevPrice  = $price['website_price'];
                $prevQty    = $price['price_qty'];
				if($price['tier_type'] == 1 && $price['price_qty'] <= 100){
					$off = ($price['website_price'] * $product->getPrice())/100;
					$prevPrice = $product->getPrice()  - $off; 
					
				}
                $prevGroup  = $price['cust_group'];
            }
            return $prevPrice;
        } else {
            foreach ($prices as $i=>$price) {
                if ($price['cust_group']!=$custGroup && $price['cust_group']!=$allGroups) {
                    unset($prices[$i]);
                }
            }
        }

        return ($prices) ? $prices : array();
    }
}
?>

At last register all these override into config.xml.

File:-/app/code/local/Mypackage/Catalog/etc/config.xml

<?xml version="1.0"?>
<config>

	<modules>
	   <Mypackage_Catalog>
		 <version>0.1.0</version>
	   </Mypackage_Catalog>
	</modules>
	
		
    <global>
		<models>
            <catalog>
                <rewrite>
					<product_type_price>Mypackage_Catalog_Model_Product_Type_Price</product_type_price>
					<product_attribute_backend_tierprice>Mypackage_Catalog_Model_Product_Attribute_Backend_Tierprice</product_attribute_backend_tierprice>
				</rewrite>
			</catalog>							
			<catalog_resource_eav_mysql4>
                <rewrite>
					<product_attribute_backend_tierprice>Mypackage_Catalog_Model_Resource_Eav_Mysql4_Product_Attribute_Backend_Tierprice</product_attribute_backend_tierprice>
                </rewrite>							
			</catalog_resource_eav_mysql4>
		</models>
	</global>

</config>

Register this local catalog module in etc.

File:/app/etc/modules/Mypackage_Catalog.xml

<?xml version="1.0"?>
<config>
	<modules>

		<Mypackage_Catalog>
			<active>true</active>
			<codePool>local</codePool>
		</Mypackage_Catalog>

	</modules>
</config>

How long customer is inactive ?

$customer = Mage::getSingleton('customer/session')->getCustomer();
$log = Mage::getModel('log/customer')->load($customer->getId());
$inctive_time = now() - $log->getLastVisitAt();

Here I come to know about an awesome feature of Magento. When we add any eav attribute to an entity we can give a backend model name. Whenever Entity will be loaded magento initiates Mage_Eav_Model_Entity_Attribute model for each attribut. If it finds any backend model name for a eav attribut, it loads the corresponding model and based on what it is doing it will call different method from that model.

Here I am giving a complete example how you can use this feature. We will add an attribue to address model as “address_verified” , use a backend model to set this value whenever the any address will be save.

Step 1.Create a custom model “Mymodule”

Step 2.Write an sql setup for this module. It will add an “address_verified” attribute to address entity

<?php $installer = $this; $installer->startSetup();

$installer->run("
INSERT INTO {$this->getTable('eav_attribute')}  (
`entity_type_id` ,
`attribute_code` ,
`attribute_model` ,
`backend_model` ,
`backend_type` ,
`backend_table` ,
`frontend_model` ,
`frontend_input` ,
`frontend_input_renderer` ,
`frontend_label` ,
`frontend_class` ,
`source_model` ,
`is_global` ,
`is_visible` ,
`is_required` ,
`is_user_defined` ,
`default_value` ,
`is_searchable` ,
`is_filterable` ,
`is_comparable` ,
`is_visible_on_front` ,
`is_html_allowed_on_front` ,
`is_unique` ,
`is_used_for_price_rules` ,
`is_filterable_in_search` ,
`used_in_product_listing` ,
`used_for_sort_by` ,
`is_configurable` ,
`apply_to` ,
`position` ,
`note` ,
`is_visible_in_advanced_search`
)
VALUES (
'2', 'is_validated', NULL , 'customer_entity/address_attribute_backend_validate', 'int', NULL , NULL , 'text', NULL , NULL , NULL , NULL , '1', '1', '0', '0', NULL , '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '', '', '', '0'
);

");

$installer->endSetup(); 

Step3.Write the back end model in your local code pool


<?php 

class Mypackage_Customer_Model_Entity_Address_Attribute_Backend_Validate
	extends Mage_Eav_Model_Entity_Attribute_Backend_Abstract
{
	public function beforeSave($object)
	{
		//Write your code to validate address
		$object->setIsValidated($satoriStatus);
		return $this;
    }
}

Step 4. Override the backend model so that it runs from your local pool

</config>
 <models>
 <customer_entity>
 <rewrite>
 <address_attribute_backend_satori>Mypackage_Customer_Model_Entity_Address_Attribute_Backend_Satori</address_attribute_backend_satori>
 </rewrite>
 </customer_entity>
 </models>
<config>

Magento has an awesome way to manage configuration values. Under Admin>System>Configuration all useful configuration for different module resides. Today I am going to show you how to create a new configuration value in admin and how use them from your code.

For example Lets create 2 fields under configuration, Enable Minimum Production Calculation , a drop down with Yes/No value and another a text input field Minimum Production Cost

Step 1:ย 

Set path for your configuration field in \app\code\local\Mypackage\Mymodule\etc\Config.xml by create a default node under config.


<?xml version="1.0"?>
<config>

    <modules>
        <Mypackage_Mymodule>
            <version>0.3.0</version>
        </Mypackage_Mymodule>
    </modules>

	<global>

        <models>
            <mymodule>
                <class>Mypackage_Mymodule_Model</class>
                <resourceModel>mymodule_mysql4</resourceModel>
            </mymodule>
            <mymodule_mysql4>
                <class>Mypackage_Mymodule_Model_Mysql4</class>
                <entities>
                    <mymodule>
                        <table>mytablename</table>
                    </mymodule>
                </entities>
            </mymodule_mysql4>
        </models>

        <resources>
            <mymodule_setup>
                <setup>
                    <module>Mypackage_Mymodule</module>
                </setup>
                <connection>
                    <use>core_setup</use>
                </connection>
            </mymodule_setup>
            <mymodule_write>
                <connection>
                    <use>core_write</use>
                </connection>
            </mymodule_write>
            <mymodule_read>
                <connection>
                    <use>core_read</use>
                </connection>
            </mymodule_read>
        </resources>

	    <helpers>
            <mymodule>
                <class>Mypackage_Mymodule_Helper</class>
            </mymodule>
        </helpers>

    </global>
	<!-- Create we create config path for cofiguration -->

	<default>
		<!-- Under checkout/mimimumproduction we create out config paths and their default values -->
		<checkout>
			<minimumproduction>
				<!-- Config path checkout/mimimumproduction/minimum_production_enabled with defaule value 1 -->
				<minimum_production_enabled>1</minimum_production_enabled>
				<!-- Config path checkout/mimimumproduction/minimum_production_cost with defaule value 200 -->
				<minimum_production_cost>200</minimum_production_cost>

			</minimumproduction>
		</checkout>
	</default>
</config>

That’s it, now can from your code you can access this config values using Mage::getStoreConfigFlag() and Mage::getStoreConfig like following:-

//return true false based on config settings
Mage::getStoreConfigFlag('checkout/minimumproduction /minimum_production_enabled');
//return 200
Mage::getStoreConfig('checkout/minimumproduction/minimum_production_cost');

But still you are not done.Customer not gonna change these values from XML. You need to give your client a way to set these values from admin panel. So, lets make our hands dirty on admin panel changing ๐Ÿ™‚

Step 2:-

Create your configuraion alias node under \app\code\local\Mypackage\Mymodule\etc\system.xml

<?xml version="1.0"?>

<config>
    <sections>
        <checkout translate="label" module="checkout">

			<!-- If want to set these config values under youw own module, only then change the following commented fields -->
			<!--
            <label>Checkout</label>
            <tab>sales</tab>
            <frontend_type>text</frontend_type>
            <sort_order>305</sort_order>
            <show_in_default>1</show_in_default>
            <show_in_website>1</show_in_website>
            <show_in_store>0</show_in_store> -->

            <groups>

				<!-- Create a field group for your config paths -->
                <minimumproduction translate="label">
                    <label>Checkout Minimum Production Cost</label>
                    <frontend_type>text</frontend_type>
                    <sort_order>500</sort_order>
                    <show_in_default>1</show_in_default>
                    <show_in_website>1</show_in_website>
                    <show_in_store>1</show_in_store>

					<!-- List your config values here -->
                    <fields>

						<!-- This goes for checkout/minimumproduction/minimum_production_enabled -->
						<minimum_production_enabled translate="label">
                            <label>Enable Minimum Production Calculation</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>
                        </minimum_production_enabled>

						<!-- This goes for checkout/minimumproduction/minimum_production_cost -->
						<minimum_production_cost translate="label">
                            <label>Minimum Production Cost</label>
                            <frontend_type>text</frontend_type>
                            <sort_order>2</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                        </minimum_production_cost>

                    </fields>

                </minimumproduction>

            </groups>

        </checkout>

    </sections>

</config><!--more-->

Ya, now you are done. If you go to Admin>System>Configuration you can see a new field group with name Checkout Minimum Production Cost created, under which you will find your configuration values with default values. You can change your default settings from here.

Have a happy time with Magento ๐Ÿ˜€ !!!

Create a magento module

Magento module

Modules are the core functioning unit in a Magento system. Here I am giving an overview of how to write a “Hello World” module in magento.

Simple basics before start you cooking ๐Ÿ™‚

At the time of instantiating, magento system reads all the Xmls inside the folder /app/etc/modules/ to get the list of active modules and their corresponding code repository . So very first step of creating a magento module is to declare the module and its core repository(the repository of the module, in magento it’s calles codepool ).

If you open /app/code/ you will see 3 coodpool :- core, community and local.

app/
|–code/
| |—community/
| |—core/
| |—local/
|

The “core” cood pool is dedicated for magento’s all system modules. The “community” codepool is for all modules developed by magento’s partners and local is the codepool dedicated for you as a developer to write your own customized code.

In Magentos’ all modules are organized under a package. This package is nothing but a simple folder under codepool containing different modules. For example all core modules of magento system is kept unde package “Mage” (open the folder /app/code/code/ , you see the folder “Mage” under which all system module resides).

Before start cooking lets fixup the name of our module is Mymodule and our package name is Mypackage .

1.Declare your shell module and it’s code pool

Create a xml file /app/etc/modules/Mymodule.xml (You can use any name, even you can use a single file to declare number of modules).

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

2.Create the basic structure Under /app/code/core/local/ :-

Mypackage/
|–Mymodule/
| |–Block/
| |–controllers/
| |–etc/
| |–Helper/
| |–sql/
|

3.Write the front controller /controllers/IndexController.php

<?php

   class Mypackage_Mymodule_IndexController extends Mage_Core_Controller_Front_Action
   {
      public function indexAction()
      {

         //Do nothing fo the time being

         $this->loadLayout();
         $this->_initLayoutMessages('customer/session');
         $this->renderLayout();
      }
   }

4.Create design layout for our controller action
/app/design/frontend/default/default/layout/mymodule.xml

   <?xml version="1.0"?>
   <layout version="0.1.0">
      <default>
      </default>
      <mymodule_index_index>

         <remove name="right"/>
         <remove name="left"/>

         <reference name="root">
            <action method="setTemplate"><template>page/1column.phtml</template></action>
         </reference>

         <reference name="content">
            <block type="mymodule/helloworld" name="helloworld" template="mymodule/helloworld.phtml"/>
         </reference>
      </mymodule_index_index>
   </layout>

4.Create associated block
/Block/Helloworld.php

<?php
   class Mypackage_Mymodule_Block_Helloworld extends Mage_Core_Block_Template
   {
      public function getHelloWorldMsg()
      {
         return "Hello world";
      }
   }
&#91;/sourcecode&#93;
<h3>5.Create Helper for this module
<em>/Helper/Data.php</em></h3>


<?php

   class Mypackage_Mymodule_Helper_Data extends Mage_Core_Helper_Abstract
   {

   }

&#91;/sourcecode&#93;
<h3>6.Now organize every thing write the settings for this module in
<em>/etc/config.xml</em></h3>
We declare the following things in out config.xml

i) Version number of the module. Magento keep track to version number in "core_resource" table which is used to run sql_setup[Details discussed in another post] .

ii) Router information for this module. It contains frontanme and access privilege (front end controller or admin ).

iii) Which layout xml to use for its design.

iv) Global path for module , blocks and helper .

v) Default connection to use for db read &amp; write.



<?xml version="1.0"?>
   <config>
      <!-- i.Version Number -->
      <modules>
         <Mypackage_Mymodule>
            <version>0.1.0</version>
         </Mypackage_Mymodule>
      </modules>
      <!-- ii. Router information -->
      <frontend>
         <routers>
            <mymodule>
                 <!-- Means front end controller -->
                  <use>standard</use>
                  <!-- Fron name "Myfrontname" declared for "Mypackage_Mymodule" -->
                  <args>
                     <module>Mypackage_Mymodule</module>
                     <frontName>myfrontname</frontName>
                  </args>
            </mymodule>
         </routers>
         <!-- iii. Desing layout file -->
         <layout>
            <updates>
               <mymodule>
                  <file>mymodule.xml</file>
               </mymodule>
            </updates>
         </layout>
      </frontend>

      <global>
         <!-- iv. Global path for model, blocks, helper -->
         <!-- models reside under path "Mypackage/Mymodule/model/" -->
         <models>
            <mymodule>
               <class>Mypackage_Mymodule_Model</class>
            </mymodule>
         </models>
         <!-- blocks reside under path "Mypackage/Mymodule/Blocks/" -->
         <blocks>
            <mymodule>
               <class>Mypackage_Mymodule_Block</class>
            </mymodule>
         </blocks>
         <!-- Helper reside under path "Mypackage/Mymodule/Helper/" -->
         <helpers>
            <mymodule>
               <class>Mypackage_Mymodule_Helper</class>
            </mymodule>
         </helpers>
         <!-- v. Declaring db connections -->
         <!-- Also sql setup handler declared in this portion -->
         <resources>
            <mymodule_write>
               <connection>
                  <use>core_write</use>
               </connection>
            </mymodule_write>

            <mymodule_read>
               <connection>
                  <use>core_read</use>
               </connection>
            </mymodule_read>
         </resources>

      </global>
   </config>

That’s it. Go to http://yourdomain.come/magentopath/myfrontname/ and see your first magento modules output ๐Ÿ™‚