Magento tutorial – Migrating to Magento 2.0

Finally, the long awaited Magento 2.0 was launched in November last year with new exciting features. Since its launch, Magento 1.x store owners have been planning to move their stores to Magento 2.0. They have been exploring different options to smoothly upgrade their stores to Magento 2.0. At the same time, most Magento store owners are in a fix as they find it difficult to decide about what is the right time to Migrate to Magento 2.0, how difficult or painful the move would be and whether or not it is worth it.

When to Migrate to Magento 2.0?
The right time to migrate to Magento 2 really depends upon your store and its current condition. If your current store is functioning smoothly with no issues and not running a very outdated version, there should be no rush for migration. But you should definitely start exploring Magento 2.0 as you have to migrate in the long run to enjoy the new enhanced features of Magento 2.

However, if your store is having performance issues or using a very old Magento 1 version, it is the right time to migrate to Magento 2.0.

Is the Move painful or smooth?
Let’s face it. You are not going to get a smooth migration. At the same time, it’s not too painful either. Yes, there are migration tools that can help you with data migration, but theme and customizations migration are not directly transferrable. Hence, extra investment would be needed for complete migration.

This extra investment should be considered as a positive thing as it will give you new ideas to improve your store. Moreover, you can refresh your store by getting rid of unnecessary logs and legacy code.

Is it worth it?
Change is always better. Magento 2 is out with all its new and attractive features, so if you are planning to be a market leader in your niche, you should prepare yourself for migration right now.

Steps in Magento Migration:
We need to migrate four components when migrating from Magento 1 to Magento 2. Data, Themes, Extensions and Customizations.

Theme Migration:
Magento 1 theme is not directly transferrable to Magento 2. However, you can do any of the following.

  • Ask a frontend developer or designer to create a brand new theme for your Magento 2 store. This is a good chance for you to make sure the new theme is responsive and follow best practices.
  • You can install any of the available theme from Magento Marketplace.

Extension Migration:
Next, extensions installed on your current site should be migrated to Magento 2 store. The problem here is that most Magento 1 extensions are not compatible with Magento 2. Extension providers often offer separate versions of their products for Magento 1 and Magento 2. They are available for purchase or freely downloadable from the Magento Marketplace.  Install only relevant extensions.

Customizations Migration:
The code migration is relatively easier as it is compatible with Magento 2 in most cases. Moreover, there is a tool available named Code Migration Toolkit that can help with the code migration process. However, due to platform differences, the output may require additional work to make sure it is successfully installed on the new store.

The Code Migration Toolkit helps by providing scripts that automatically convert custom Magento 1.x modules to version 2.

Data Migration:
The last and most important step is to migrate your data from Magento 1 to Magento 2 store. You can use a tool called Data Migration Tool to perform this. Below are the steps to follow to migrate your data from Magento 1 to the new store running Magento 2.

  • Provide the Data Migration Tool with a network access to connect to Magento 1 and Magento 2 databases. Open ports in your firewall.
  • Put all activity in the Magento 1.x Admin Panel on hold (except for order management activities such as creating invoice, shipping etc.).
  • Do the same for all Magento 1.x cron jobs.
  • Make use of the migration tool to migrate settings and websites.
  • Copy your Magento 1.x media files to Magento 2.0. (You have to copy them manually from <magento1-root>/media to <magento2-root>/pub/media)
  • Migrate your data from Magento 1 to Magento 2 database using Data Migration Tool.
  • Use the magento indexer:reindex</code> command to reindex all indexers.
  • Test your Magento 2.0 site to ensure it works.

It is recommended to hire a professional Magento developer for Magento migration. The steps listed above are not perfect and you may require plenty of manual work for successful migration especially in theme and customization migration which can potentially lead you to problems if you are not a Magento expert.

Magento tutorial – Adding Custom fields to the order and/or checkout page

Sometimes you need to add custom fields to order / checkout page to make it more interactive. Magento Custom fields are used to collect more information about your customer and product. This blog demonstrates how to add custom field to checkout in billing step and the method works for all Magento 1 versions. Following is a step by step example of adding a single custom field in the billing step.

Step 1: Adding HTML

The following code will add a text field to the billing.phtml file.
For magento 1.6(-) the file to edit is checkout/onepage/billing.phtml and for magento 1.6(+) you need to edit file persistent/checkout/onepage/billing.phtml. Open the phtml file, find the code

<?php if ($this->canShip()): ?>

and just above the line add this

<li class="fields">

<div class="field">

<label for="billing:ssn" class="required"><em>*</em><?php echo $this->__('SSN') ?></label>

<div class="input-box">

<input type="text" name="custom[ssn]" value="<?php echo $this->htmlEscape($this->getQuote()->getSsn()) ?>" title="<?php echo $this->__('SSN') ?>" class="input-text required-entry" id="billing:ssn" />

</div>

</div>

</li>

 

Step2: Save the field in Quote and Order Tables

Create two tables. ‘sales_quote_custom’ for sales and ‘sales_order_custom’for order. Open phpmyadmin and confirm if the quote and order tables are created. Next we need to write some event observers to capture quote save, and load events. So open your modules config.xml file and inside the <global> tag put in

<events>

<sales_quote_save_before> <!-- Event Called Before Quote Object is saved -->

<observers>

<save_before>

<type>singleton</type>

<class>Excellence_Custom_Model_Observer</class> <!-- Over Model Class -->

<method>saveQuoteBefore</method> <!-- name of function -->

</save_before>

</observers>

</sales_quote_save_before>

<sales_quote_save_after> <!-- Event called After Quote Object is saved -->

<observers>

<save_after>

<type>singleton</type>

<class>Excellence_Custom_Model_Observer</class> <!-- Over Model Class -->

<method>saveQuoteAfter</method> <!-- name of function -->

</save_after>

</observers>

</sales_quote_save_after>

<sales_quote_load_after> <!-- Event called when Quote Object is loaded -->

<observers>

<load_after>

<type>singleton</type>

<class>Excellence_Custom_Model_Observer</class> <!-- Over Model Class -->

<method>loadQuoteAfter</method> <!-- name of function -->

</load_after>

</observers>

</sales_quote_load_after>

<sales_model_service_quote_submit_after> <!-- Event called after order placed -->

<observers>

<sales_model_service_quote_submit_after>

<type>singleton</type>

<class>Excellence_Custom_Model_Observer</class> <!-- Over Model Class -->

<method>saveOrderAfter</method> <!-- name of function -->

</sales_model_service_quote_submit_after>

</observers>

</sales_model_service_quote_submit_after>

<sales_order_load_after> <!-- Event called after Order Object is loaded -->

<observers>

<sales_order_load_after>

<type>singleton</type>

<class>Excellence_Custom_Model_Observer</class> <!-- Over Model Class -->

<method>loadOrderAfter</method> <!-- name of function -->

</sales_order_load_after>

</observers>

</sales_order_load_after>

</events>

and next we need to create our Observer classes in Model folder. So create an Observer.php in your modules Model folder.

<?php
class Excellence_Custom_Model_Observer{ 

public function saveQuoteBefore($evt){

$quote = $evt->getQuote();

$post = Mage::app()->getFrontController()->getRequest()->getPost();

if(isset($post['custom']['ssn'])){

$var = $post['custom']['ssn'];

$quote->setSsn($var);

}

}

public function saveQuoteAfter($evt){

$quote = $evt->getQuote();

if($quote->getSsn()){

$var = $quote->getSsn();

if(!empty($var)){

$model = Mage::getModel('custom/custom_quote');

$model->deteleByQuote($quote->getId(),'ssn');

$model->setQuoteId($quote->getId());

$model->setKey('ssn');

$model->setValue($var);

$model->save();

}

}

}

public function loadQuoteAfter($evt){

$quote = $evt->getQuote();

$model = Mage::getModel('custom/custom_quote');

$data = $model->getByQuote($quote->getId());

foreach($data as $key => $value){

$quote->setData($key,$value);

}

}

public function saveOrderAfter($evt){

$order = $evt->getOrder();

$quote = $evt->getQuote();

if($quote->getSsn()){

$var = $quote->getSsn();

if(!empty($var)){

$model = Mage::getModel('custom/custom_order');

$model->deleteByOrder($order->getId(),'ssn');

$model->setOrderId($order->getId());

$model->setKey('ssn');

$model->setValue($var);

$order->setSsn($var);

$model->save();

}

}

}

public function loadOrderAfter($evt){

$order = $evt->getOrder();

$model = Mage::getModel('custom/custom_order');

$data = $model->getByOrder($order->getId());

foreach($data as $key => $value){

$order->setData($key,$value);

}

}

}

 

Step3: Display Our Field in My Account -> View Order

After the order is placed by the customer, our custom fields needs to be visible in My Account. So to do this in our module fronted layout file, in my case its custom.xml.

<?xml version="1.0"?>

<layout version="0.1.0">

<sales_order_view>

<reference name="my.account.wrapper">

<block type="custom/custom_order" name="custom.order" template="custom/order.phtml" after='sales.order.info' />

</reference>

</sales_order_view>

</layout>

 

This layout file is simple and understandable. Basically, we are taking reference of my.account.wrapper block and adding a child block to it. Our block type is custom/order_view and template file is custom/order.phtml.
So we need to create our block class

<?php

class Excellence_Custom_Block_Custom_Order extends Mage_Core_Block_Template{

public function getCustomVars(){

$model = Mage::getModel('custom/custom_order');

return $model->getByOrder($this->getOrder()->getId());

}

public function getOrder()

{

return Mage::registry('current_order');

}

}

and our order.phtml file

<div class="col-set order-info-box">

<div class="col">

<div class="box">

<div class="box-title">

<h2><?php echo $this->__('Custom Fields') ?></h2>

</div>

<div class="box-content">

<?php

$custom = $this->getCustomVars();

foreach($custom as $key => $value){

?>

<b><?php echo $this->__($key);?></b> : <?php echo $value;?> <br/>

<?php } ?>

</div>

</div>

</div>

</div>

 

Step4: Admin Order View Page

Next we need to show our custom field in Admin -> Order -> View Order page. To do this, in our adminhtml layout file, in my case custom.xml we will put in this code.

<?xml version="1.0"?>

<layout version="0.1.0">

<adminhtml_sales_order_view>

<reference name="order_info">

<action method='setTemplate'><template>custom/sales/order/info.phtml</template></action>

<block type="adminhtml/sales_order_view_info" name="order_info2" template="sales/order/view/info.phtml"></block>

<block type="custom/adminhtml_custom_order" name="custom.order" template='custom/order.phtml'/>

</reference>

</adminhtml_sales_order_view>

</layout>


So basically here we have added my block “custom.order” to the existing order_info block. So the code for block class custom/adminhtml_custom_order would be

<?php

class Excellence_Custom_Block_Adminhtml_Custom_Order extends Mage_Adminhtml_Block_Sales_Order_Abstract{

public function getCustomVars(){

$model = Mage::getModel('custom/custom_order');

return $model->getByOrder($this->getOrder()->getId());

}

}

and next we need to create their phtml files

custom/order.phtml

<?php $_order = $this->getOrder() ?>

<div class="box-left">

<div class="entry-edit">

<div class="entry-edit-head">

<h4 class="icon-head head-account"><?php echo Mage::helper('sales')->__('Custom Fields') ?></h4>

</div>

<div class="fieldset">

<table cellspacing="0" class="form-list">

<?php

$custom = $this->getCustomVars();

foreach($custom as $key => $value){

?>

<tr>

<td style="width:10%" class="label"><strong><?php echo Mage::helper('sales')->__($key) ?></strong></td>

<td class="value"><?php echo $value;?></td>

</tr>

<?php } ?>

</table>

</div>

</div>

</div>

<div class="clear"></div>

custom/sales/order/info.phtml

<?php echo $this->getChildHtml('order_info2');?>

<?php echo $this->getChildHtml('custom.order');?>

Step5: Adding Custom Fields to Order Email

To do this open the order email template located at
app\locale\en_US\template\email\sales\order_new.html
app\locale\en_US\template\email\sales\order_new_guest.html
add the below code where you want

{{depend order.hasCustomFields()}}

<table cellspacing="0" cellpadding="0" border="0" width="650">

<thead>

<tr>

<th align="left" width="325" bgcolor="#EAEAEA" style="font-size:13px; padding:5px 9px 6px 9px; line-height:1em;">Custom Fields:</th>

</tr>

</thead>

<tbody>

<tr>

<td valign="top" style="font-size:12px; padding:7px 9px 9px 9px; border-left:1px solid #EAEAEA; border-bottom:1px solid #EAEAEA; border-right:1px solid #EAEAEA;">

{{var order.getFieldHtml()}}

&nbsp;

</td>

</tr>

</tbody>

</table>

{{/depend}}

<br/>

So as per the above code, we need to two functions hasCustomFields() and getFieldHtml() in our Order class. So next we will override the Mage_Sales_Model_Order model. Open your config.xml file and inside <models> section put in this code

<sales>

<rewrite>

<order>Excellence_Custom_Model_Sales_Order</order>

</rewrite>

</sales>

and next create our new model class Excellence_Custom_Model_Sales_Order

<?php

class Excellence_Custom_Model_Sales_Order extends Mage_Sales_Model_Order{

public function hasCustomFields(){

$var = $this->getSsn();

if($var && !empty($var)){

return true;

}else{

return false;

}

}

public function getFieldHtml(){

$var = $this->getSsn();

$html = '<b>SSN:</b>'.$var.'<br/>';

return $html;