Friday, August 16, 2013

Magento : How to cache custom data into Magento

Use following code in configuration file as
<global>
    <cache>
        <types>
            <namespace_module module="namespace_module" translate="label description">
                <label>Your modules cache label</label>
                <description>Description of your modules cache</description>
                <tags>YOUR_MODULES_CACHE_TAGS</tags>
            </namespace_module>
        </types>
    </cache>
</global>
Then create a model class file witha variable and a method as
const CACHE_TAG_NAMESPACE_MODULE = 'YOUR_MODULES_CACHE_TAGS';
$cacheGroup = 'namespace_module';
$useCache = Mage::app()->useCache($cacheGroup);
if (true === $useCache) {
    // Cache is active
    $cacheId = "unique_name";
    if ($cacheContent = Mage::app()->loadCache($cacheId)) {
    $html = $cacheContent;
    return $html;
    }else{

    try {
        $cacheContent = $html;
        $tags = array(model::CACHE_TAG_NAMESPACE_MODULE);
        $lifetime = Mage::getStoreConfig('core/cache/lifetime');
        Mage::app()->saveCache($cacheContent, $cacheId, $tags, $lifetime);
        } catch (Exception $e) {
        // Exception = no caching
        Mage::logException($e);
    }
    return $html;
    }
} else {
    // Cache is not active
    return $html;
}

Also we can following code for clean the cache
Mage::app()->removeCache($cacheId);


By default Magento uses its file system to save cache (files located in the directory var/cache/).
Another option is the database, which is slower then the files option mostly because the database is a heavily used resource for Magento instances anyway. Then there are storage schemes that use RAM (which are much faster), e.g. APC (shared memory) or memcached (a networked caching server) or Redis.

The Magento cache is organized by tags, this means you have cache entries which belongs to a cache group.

APC is an opcode cache for PHP. It is a framework for caching and optimizing PHP code. APC also serves as a user cache. APC cache is stored in memory where performance gains over file system cache are huge.
There following step to configure APC in Magento
1. Install php5-apc package (like sudo apt-get install php5-apc)
2. Edit and configure setting in apc.ini
3. Add the following code between the global tags in app/etc/local.xml.
<global>
<cache>
            <backend>apc</backend>
            <prefix>mystore_</prefix>
        </cache>
</global>

There following step to configure Memcache as a Fast Backend in Magento
1. Install Memcache as a PHP extension (apt-get install memcached )
2. And enable it in your php.ini
3. Add the following code between the global tags in app/etc/local.xml.
<cache>
<backend>memcached</backend>
<!-- apc / memcached / empty=file -->
<memcached>
<!-- memcached cache backend related config -->
<servers>
<!-- any number of server nodes can be included -->
<server>
<host><![CDATA[127.0.0.1]]></host>
<port><![CDATA[11211]]></port>
<persistent><![CDATA[1]]></persistent>
</server>
</servers>
<compression><![CDATA[0]]></compression>
<cache_dir><![CDATA[]]></cache_dir>
<hashed_directory_level><![CDATA[]]></hashed_directory_level>
<hashed_directory_umask><![CDATA[]]></hashed_directory_umask>
<file_name_prefix><![CDATA[]]></file_name_prefix>
</memcached>
</cache>

There following step to configure Redis as a Fast Backend in Magento
1. Install redis (2.4+ required)
2. Install phpredis
3. Install the magento extension “Cm_Cache_Backend_Redis”
4. Add the following code between the global tags in app/etc/local.xml.
<cache>                                              
<backend>Zend_Cache_Backend_Redis</backend>                            <slow_backend>database</slow_backend>                                  <slow_backend_store_data>0</slow_backend_store_data>                   <auto_refresh_fast_cache>0</auto_refresh_fast_cache>
<backend_options>                                              
<server><![CDATA[127.0.0.1]]></server>
<port><![CDATA[11211]]></port>                                              
<database>database</database>                                        
<use_redisent>0</use_redisent>  <!-- 0 for phpredis, 1 for redisent -->                                                <automatic_cleaning_factor>0</automatic_cleaning_factor> <!-- optional, 20000 is the default, 0 disables auto clean -->
</backend_options>
</cache>

Monday, July 29, 2013

Magento : Install Magento 1.7.0.2 With Sample Data By SSH

mkdir myproject
cd myproject
wget http://www.magentocommerce.com/downloads/assets/1.7.0.2/magento-1.7.0.2.tar.gz
wget http://www.magentocommerce.com/downloads/assets/1.6.1.0/magento-sample-data-1.6.1.0.tar.gz
tar -zxvf magento-1.7.0.2.tar.gz
tar -zxvf magento-sample-data-1.6.1.0.tar.gz
mv magento-sample-data-1.6.1.0/media/* magento/media/
mv magento-sample-data-1.6.1.0/magento_sample_data_for_1.6.1.0.sql magento/data.sql
mv magento/* magento/.htaccess .
chmod o+w var var/.htaccess app/etc
chmod -R o+w media
mysql -h localhost -u -p myproject_db < data.sql
chmod 755 mage
./mage mage-setup.

Wednesday, July 17, 2013

Magento : Create/Collocate Magento System Configuration

First create a blank module with following files
 etc/modules/Bd_Systemconfigdemo.xml
Bd/Systemconfigdemo/etc/config.xml

Then create a system.xml file in  Bd/Systemconfigdemo/etc/system.xml with following code
<?xml version="1.0"?>
<config>
      <tabs>
        <demo_tab translate="label" module="systemconfigdemo">
            <label>Demo Tab</label>
            <sort_order>0</sort_order>
        </demo_tab>
      </tabs>
      <sections>
        <demo_section  translate="label" module="systemconfigdemo">                   
        <label>Demo Section</label>
        <tab>demo_tab</tab>
        <frontend_type>text</frontend_type>
        <sort_order>0</sort_order>
        <show_in_default>1</show_in_default>
        <show_in_website>1</show_in_website>
        <show_in_store>1</show_in_store>           
                    <groups>
                      <demo_group translate="label">
                      <label>Demo Group</label>
                      <frontend_type>text</frontend_type>
                      <sort_order>0</sort_order>
                      <show_in_default>1</show_in_default>
                      <show_in_website>1</show_in_website>
                      <show_in_store>1</show_in_store>
                       <fields>
                          <demo_field1 translate="label">
                            <label>Demo Field1</label>
                            <frontend_type>text</frontend_type>
                            <sort_order>0</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                            <comment>first</comment>
                          </demo_field1>
                          <demo_field2 translate="label">
                            <label>Demo Field2</label>
                            <frontend_type>select</frontend_type>
                            <source_model>adminhtml/system_config_source_yesno</source_model>
                            <sort_order>0</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                            <comment>second</comment>
                          </demo_field2>
                       </fields>
                       </demo_group>
                    </groups>
        </demo_section>
      </sections>
</config>


And adminhtml.xml with following code
<?xml version="1.0"?>
    <config>
        <acl>
            <resources>
                <admin>
                    <children>
                        <system>
                            <children>
                                <config>
                                    <children>
                                        <demo_section translate="title" module="systemconfigdemo">
                                            <title>Demo Section Section</title>
                                            <sort_order>0</sort_order>
                                        </demo_section>
                                    </children>
                                </config>
                            </children>
                        </system>
                    </children>
                </admin>
            </resources>
        </acl>
    </config>

Magento : Add New Order Total (fee or discount, like prepaid discount)

Here i consider that i need to give a discount when user make a order with prepaid method.

Consider, Bd_Prepaid is a custom module and prepaiddiscount_total is a variable,

First create a simple module
1. etc/modules/Bd_Prepaid
<?xml version="1.0"?>
<config>
  <modules>
    <Bd_Prepaid>
      <active>true</active>
      <codePool>local</codePool>
      <version>0.1.0</version>
    </Bd_Prepaid>
  </modules>
</config>

2.Then create a config file with following code
<?xml version="1.0"?>
<config>
  <modules>
    <Bd_Prepaid>
      <version>0.1.0</version>
    </Bd_Prepaid>
  </modules>
  <global>
    <helpers>
      <prepaid>
        <class>Bd_Prepaid_Helper</class>
      </prepaid>
    </helpers>
    <models>
      <prepaid>
        <class>Bd_Prepaid_Model</class>
        <resourceModel>prepaid_mysql4</resourceModel>
      </prepaid>
    </models>
    <resources>
      <salesattribute1374123678_setup>
        <setup>
          <module>Bd_Prepaid</module>
          <class>Mage_Sales_Model_Mysql4_Setup</class>
        </setup>
        <connection>
          <use>core_setup</use>
        </connection>
      </salesattribute1374123678_setup>
      <salesattribute1374123678_write>
        <connection>
          <use>core_write</use>
        </connection>
      </salesattribute1374123678_write>
      <salesattribute1374123678_read>
        <connection>
          <use>core_read</use>
        </connection>
      </salesattribute1374123678_read>
    </resources>
    <events>
    <checkout_type_onepage_save_order_after> <!-- identifier of the event we want to catch -->
        <observers>
          <checkout_type_onepage_save_order_after_prepaiddiscount_handler> <!-- identifier of the event handler -->
            <type>model</type> <!-- class method call type; valid are model, object and singleton -->
            <class>prepaid/newordertotalobserver</class> <!-- observers class alias -->
            <method>savePrepaiddiscountTotal</method>  <!-- observer's method to be called -->
            <args></args> <!-- additional arguments passed to observer -->
          </checkout_type_onepage_save_order_after_prepaiddiscount_handler>
        </observers>
      </checkout_type_onepage_save_order_after>       
    <checkout_type_multishipping_create_orders_single> <!-- identifier of the event we want to catch -->
        <observers>       
          <checkout_type_multishipping_create_orders_single_prepaiddiscount_handler> <!-- identifier of the event handler -->
            <type>model</type> <!-- class method call type; valid are model, object and singleton -->
            <class>prepaid/newordertotalobserver</class> <!-- observers class alias -->
            <method>savePrepaiddiscountTotalForMultishipping</method>  <!-- observer's method to be called -->
            <args></args> <!-- additional arguments passed to observer -->
          </checkout_type_multishipping_create_orders_single_prepaiddiscount_handler>       
        </observers>
      </checkout_type_multishipping_create_orders_single>
    </events>   
     <sales>
        <quote>
            <totals>               
                <prepaiddiscount_total>
                    <class>prepaid/quote_address_total_prepaiddiscount</class>
                    <after>subtotal,freeshipping,tax_subtotal,shipping</after>
                    <before>grand_total</before>
                </prepaiddiscount_total>
            </totals>
        </quote>
            <order_invoice>
                <totals>               
                <prepaiddiscount_total>
                    <class>prepaid/order_invoice_total_prepaiddiscount</class>
                    <after>subtotal,freeshipping,tax_subtotal,shipping</after>
                    <before>grand_total</before>
                </prepaiddiscount_total>
                </totals>
            </order_invoice>
            <order_creditmemo>
                <totals>               
                <prepaiddiscount_total>
                    <class>prepaid/order_invoice_total_prepaiddiscount</class>
                    <after>subtotal,freeshipping,tax_subtotal,shipping</after>
                    <before>grand_total</before>
                </prepaiddiscount_total>
                </totals>
            </order_creditmemo>
    </sales>
  </global>
</config>

3.Then create amysql file to create a order attribute
<?php
$installer = $this;
$installer->startSetup();

$installer->addAttribute("quote_address", "prepaiddiscount_total", array("type"=>"varchar"));
$installer->addAttribute("order", "prepaiddiscount_total", array("type"=>"varchar"));
$installer->endSetup();
    
4.Then create a observer as used in config file
Like Bd/Prepaid/Model/Newordertotalobserver.php
<?php
class Bd_Prepaid_Model_Newordertotalobserver
{
     public function savePrepaiddiscountTotal(Varien_Event_Observer $observer)
    {
         $order = $observer -> getEvent() -> getOrder();
         $quote = $observer -> getEvent() -> getQuote();
         $shippingAddress = $quote -> getShippingAddress();
         if($shippingAddress && $shippingAddress -> getData('prepaiddiscount_total')){
             $order -> setData('prepaiddiscount_total', $shippingAddress -> getData('prepaiddiscount_total'));
             }
        else{
             $billingAddress = $quote -> getBillingAddress();
             $order -> setData('prepaiddiscount_total', $billingAddress -> getData('prepaiddiscount_total'));
             }
         $order -> save();
     }
   
     public function savePrepaiddiscountTotalForMultishipping(Varien_Event_Observer $observer)
    {
         $order = $observer -> getEvent() -> getOrder();
         $address = $observer -> getEvent() -> getAddress();
         $order -> setData('prepaiddiscount_total', $shippingAddress -> getData('prepaiddiscount_total'));
         $order -> save();
     }
}

5.Then create a class file to collect the total (Bd/Prepaid/Model/Quote/Address/Total/Prepaiddiscount.php), which inherited from Mage_Sales_Model_Quote_Address_Total_Abstract with following code
<?php
class Bd_Prepaid_Model_Quote_Address_Total_Prepaiddiscount
extends Mage_Sales_Model_Quote_Address_Total_Abstract
{
     public function __construct()
    {
         $this -> setCode('prepaiddiscount_total');
         }
    /**
     * Collect totals information about prepaiddiscount
     *
     * @param Mage_Sales_Model_Quote_Address $address
     * @return Mage_Sales_Model_Quote_Address_Total_Shipping
     */
     public function collect(Mage_Sales_Model_Quote_Address $address)
    {
         parent :: collect($address);
         $items = $this->_getAddressItems($address);
         if (!count($items)) {
            return $this;
         }
         $quote= $address->getQuote();

         //amount definition

         $prepaiddiscountAmount = 0.01;

         //amount definition

         $prepaiddiscountAmount = $quote -> getStore() -> roundPrice($prepaiddiscountAmount);
         $this -> _setAmount($prepaiddiscountAmount) -> _setBaseAmount($prepaiddiscountAmount);
         $address->setData('prepaiddiscount_total',$prepaiddiscountAmount);

         return $this;
     }
   
    /**
     * Add prepaiddiscount totals information to address object
     *
     * @param Mage_Sales_Model_Quote_Address $address
     * @return Mage_Sales_Model_Quote_Address_Total_Shipping
     */
     public function fetch(Mage_Sales_Model_Quote_Address $address)
    {
         parent :: fetch($address);
         $amount = $address -> getTotalAmount($this -> getCode());
         if ($amount != 0){
             $address -> addTotal(array(
                     'code' => $this -> getCode(),
                     'title' => $this -> getLabel(),
                     'value' => $amount
                    ));
         }
       
         return $this;
     }
   
    /**
     * Get label
     *
     * @return string
     */
     public function getLabel()
    {
         return Mage :: helper('prepaid') -> __('Prepaid Discount');
    }
}

6.Then create a file to add this variable in invoice and an other file to add in memo
as
Bd/Prepaid/Model/Order/Invoice/Total/Prepaiddiscount.php
<?php
class Bd_Prepaid_Model_Order_Invoice_Total_Prepaiddiscount
extends Mage_Sales_Model_Order_Invoice_Total_Abstract
{
    public function collect(Mage_Sales_Model_Order_Invoice $invoice)
    {
        $order=$invoice->getOrder();
        $PrepaiddiscountTotal = $order->getPrepaiddiscountTotal();
        if ($PrepaiddiscountTotal&&count($order->getInvoiceCollection())==0) {
            $invoice->setGrandTotal($invoice->getGrandTotal()+$orderPrepaiddiscountTotal);
            $invoice->setBaseGrandTotal($invoice->getBaseGrandTotal()+$orderPrepaiddiscountTotal);
        }
        return $this;
    }
}

Bd/Prepaid/Model/Order/Creditmemo/Total/Prepaiddiscount.php
<?php
class Bd_Prepaid_Model_Order_Creditmemo_Total_Prepaiddiscount
extends Mage_Sales_Model_Order_Creditmemo_Total_Abstract
{
    public function collect(Mage_Sales_Model_Order_Creditmemo $creditmemo)
    {

        return $this;

        $order = $creditmemo->getOrder();
        $orderPrepaiddiscountTotal        = $order->getPrepaiddiscountTotal();

        if ($orderPrepaiddiscountTotal) {
            $creditmemo->setGrandTotal($creditmemo->getGrandTotal()+$orderPrepaiddiscountTotal);
            $creditmemo->setBaseGrandTotal($creditmemo->getBaseGrandTotal()+$orderPrepaiddiscountTotal);
        }

        return $this;
    }
}

7. At last add following code to app\code\core\Mage\Sales\Block\Order\Totals.php
${code}Total=$source->getprepaiddiscountTotal();

if($source->getOrderId()) {
    ${code}Total=$source->getOrder()->getprepaiddiscountTotal();
}

$this->_totals['prepaiddiscount_total'] = new Varien_Object(array(
    'code'  => 'prepaiddiscount_total',
    'field' => 'prepaiddiscount_total',
    'value' => $prepaiddiscountTotal,
    'label' => $this->__('Prepaid Discount')
));


And following code to app\code\core\Mage\Adminhtml\Block\Sales\Totals.php
$prepaiddiscountTotal=$this->getSource()->getprepaiddiscountTotal();

if($this->getSource()->getOrderId()) {
    $prepaiddiscountTotal=$this->getSource()->getOrder()->getprepaiddiscountTotal();
}
$this->_totals['prepaiddiscount_total'] = new Varien_Object(array(
        'code'      => 'prepaiddiscount_total',
        'value'     => $prepaiddiscountTotal,
        'base_value'=> $prepaiddiscountTotal,
        'label'     => $this->__('Prepaid Discount')
));



 

Tuesday, July 2, 2013

Magento : Make 'Continue Shopping' button redirect to the last-added-to-cart product's category

Edit cart.phtml and replace following code

<?php if($this->getContinueShoppingUrl()): ?>
    <button type="button" title="<?php echo $this->__('Continue Shopping') ?>" class="button btn-continue" onclick="setLocation('<?php echo $this->getContinueShoppingUrl(); ?>')"><span><span><?php echo $this->__('Continue Shopping') ?></span></span></button>
<?php endif; ?>

with

<?php
    $lastProductAddedToCartId = Mage::getSingleton('checkout/session')->getLastAddedProductId();
    if($lastProductAddedToCartId) {
        $productCategoryIdsArray = Mage::getModel('catalog/product')->load($lastProductAddedToCartId)->getCategoryIds();
        $continueShoppingCategoryUrl = Mage::getModel('catalog/category')->load($productCategoryIdsArray[0])->getUrl();
    }
?>
<?php if($this->getContinueShoppingUrl()): ?>
        <button type="button" title="<?php echo $this->__('Continue Shopping') ?>" class="button btn-continue" onclick="setLocation('<?php echo (isset($continueShoppingCategoryUrl)) ? $continueShoppingCategoryUrl : $this->getContinueShoppingUrl(); ?>')"><span><span><?php echo $this->__('Continue Shopping') ?></span></span></button>
 <?php endif; ?>

Thursday, June 20, 2013

Magento : Create CSV file for any custom data in magento

It can be done by using Varien_File_Csv class
Exp:

$file_path = '/your_dir_path/sample.csv';
$mage_csv = new Varien_File_Csv(); //mage CSV 
$products_ids = array(1,2,3); //product ids or make array of any data
$products_model = Mage::getModel('catalog/product');
$products_row = array();
foreach ($products_ids as $pid)
{
   $prod = $products_model->load($pid);
   $data = array();
   $data['sku'] = $prod->getSku();
   $data['name'] = $prod->getName();
   $data['price'] = $prod->getPrice();    
   $products_row[] = $data;              
}
$mage_csv->saveData($file_path, $products_row);

Sunday, June 16, 2013

Magento : Order State and Status in Magento

In Magento, there are two columns in sales_flat_order table.
These are state and status, They both are different. State is used by magento to tell if the order is new, processing, complete, holded, closed, canceled, etc.

while Statuses are the one that YOU would be defining at the backend in System -> Order Statuses. Magento displays order STATUSES and not STATES in the backend order detail page to let you know which status is assigned as per your mapping.

Remember, multiple statuses can be mapped with one state, while vice versa is not possible.

Also you may know more, reading file /app/code/core/Mage/Sales/etc/config.xml