Magento Interview Question Part-2

Some more questions to go:-

1. What is EAV model? How Magento uses EAV Model?

EAV basically stands for Entity Attribute Value. I will be explaining it with an example in terms of Magento, considering the product as an Entity. We can have a various attribute for a product i.e, various column in which product related data will be stored, for example, color, product name, size, product description, length, weight etc. Now Magento manages lots of product and it is always a possibility that each type of product might not require all columns to have a value such as, if we are selling a banana then length is not needed for that, So the whole column will always be empty which will simply make our space as non-utilized. Also if we have 1000 types of product and then in total they will be using lots of columns and thus make our table very huge. So in EAV, we break the things and attribute/column are maintained as a row. Here we are mainly normalizing our tables.
Now as per Magento we have table eav_entity, which list all entity type. Eav_Attribute which has attribute/column data. And further on basis of entity and their datatype we have tables which save their value.
Thus, in short, The most widely used way to store entities is implementing attributes as columns and entities as rows.

2. List the different type of product that Magento has and mentioned when to use which one?

Simple Product:-
It is the most basic type of physical product. For example:-
I want to sell a shirt with Small size.Each simple product has a unique SKU.

Configurable Product:-
In these we provide a different option for a simple product, this allows you to select any one of those options and order. For example:-
We have a configurable product, shirt with different size such as s, m, xs, xl and color white, black, gray. This as a whole is configurable and, in admin, they all are the different simple product such as a shirt with size m and a color black. The configurable product basically ties them all together and gives the end user the choice, usually from a drop-down menu to select whichever product he wants.

Grouped Product:-
It is a “group” of simple products so that combo or several associated products can be sold as a unit. For example, let’s say we want to sell the camera lens + a memory card + a camera. Each of those items would be simple products; we want to sell them as a group so that we can sell them in an offer.

Bundled Product:-
Simple to what group product was doing but group product does give any choice to end user to select. Thus we have bundled product, for example, we can have a memory card with different warranty or of a different company. Now in bundle, we can allow a customer to choose any one of the options with the product.

Virtual Product:-
These are not the physical product, they are sort of services or anything which cannot be touched and feel. Such as cable repairing.

Downloadable product:-
A video, images anything that you can download are included in these product type.

3. What is ORM and how does it work in Magento?

ORM stands for Object Relational Mapping, it is a programming technique for converting data into objects and vice-versa. In Magento, it is implemented as a model, as all Model inherits Varien_Object class and heavily used PHP getter and setter functions to retrieve data objects.
For example:-
$product = Mage::getModel(‘catalog/product’)->setPrice(100);
echo $product->getPrice();

Above we are setting the price as 100 for product but model is not directly interacting with the database it is rather dealing with objects, not with data. Thus if we are using ORM then developer with set and get values through objects they will not be directly interacting with the database.

4. Does Magento follow Master-slave architecture, if yes then tell us how do we create that in Magento?

Yes, Magento support master-slave architecture. It is capable of splitting off reads/writes to different database servers mainly to a master and to a slave which allow us to route read request to additional servers and forwarding all the update/write queries to a single master. Let us see now how we can configure master-slave with Magento:-
In your app/etc/local.xml add a node for default_read and pass the slave database details:-

<default_setup>
    <connection>
        <host><![CDATA[Master-host]]></host>
        <username><![CDATA[user]]></username>
        <password><![CDATA[pass]]></password>
        <dbname><![CDATA[magentodb]]></dbname>
        <active>1</active>
    </connection>
</default_setup>
<default_read>
    <connection>
        <use/>
        <host><![CDATA[Slave-host]]></host>
        <username><![CDATA[user]]></username>
        <password><![CDATA[pass]]></password>
        <dbname><![CDATA[magento]]></dbname>
        <type>pdo_mysql</type>
        <model>mysql4</model>
        <initStatements>SET NAMES utf8</initStatements>
        <active>1</active>
    </connection>
</default_read> 

Secondly, you need to modify MySQL configuration file, make sure we do it before changing local.xml
Configuration for master server
edit /etc/my.cnf and add below content in the file:

[mysqld]
server-id       = 1
log_bin         = /var/log/mysql/mysql-bin.log
expire_logs_days    = 10
max_binlog_size     = 100M
binlog_do_db        = magento_demo
binlog_ignore_db    = mysql 

then restart your mysql server. Configuration for slave server edit /etc/my.cnf and add below content in the file:

[mysqld]
server-id=2
log-bin=mysql-bin
master-host=192.168.1.2
master-user=username
master-password=111111
master-port=3306
replicate-do-db=magento_demo
replicate-ignore-db=mysql
master-connect-retry=60 

then restart your mysql server.

Above changes will make your architecture ready.

5. What is the directory structure of Magento?

Below are the main files and folders that you should remember:

app (directory) – This folder contains the modules, themes, configuration and translation files. cron.php – a Cron Job should be set for this file.
downloader (directory) – This is the storage of the web downloader files. It is mainly used for installation and upgrade of Magento through your browser;
index.php – the main index file for Magento;
js (directory) – Contains the pre-compiled libraries of the JavaScript code included in Magento;
lib (directory) – The Magento core code is located in this folder. It contains the PHP libraries;
media (directory) – This stores Magento media files – images, thumbnails, uploaded products images.
skin (directory) – This directory contains – images, JavaScript files, CSS files, Flash files.
var (directory) – Cache, sessions, database backups, data exports and cached error reports can be found in this directory;

6. What is the difference between cron.php and cron.sh?

Cron.php is a PHP script and cron.sh is a shell script, cron.sh internally calls cron.php itself. We set Cron file on the server in Cron jobs when we schedule cron. If PHP variable id not set we can directly use cron.sh.

7. How Cron jobs are scheduled in Magento and what is the workflow of Cron in Magento? In which table did we manage Cron schedule?

Cron is a daemon that executes automatically at scheduled time. Sometimes we have requirements in our applications that needs to be automated such as indexing, backup of various things cannot be always taken care manually on daily basis. Thus we write scripts and set Cron them. Magento itself provide a way to configure or schedule a Cron job. Magento uses the cron.php file, which can be found in the root of your application to manage and dispatch cronjobs. The cron.php script internally executes Magento cronjob manager. It is highly recommended to set Cron job using cron.sh rather than cron.php.Cron_Schedule table manages all Cron schedule.

8. What is compilation in Magento? How does compilation improve performance?

Magento Compilation allows you to compile all Magento installation files in order to create a single include path. since all the class files are included and found at the same path it improves the class loading time and thus the performance of your online store is supposed to give between 25% and 50% increase in your page load speed. During development phase we keep compilation off, else we need to run compilation again and again. To disable Magento Compilation, go to your Admin Panel -> System -> Tools -> Compilation and click on the Disable button.
When we run compilation process Magento copies all your class, model, helper, blocks, and lib files to “includes/src” folder. We can check that by opening “includes/src” folder, there you will find the class directly inside a single folder. There will be files with the name as follows : – Mage_Catalog_Block_Breadcrum.php, Varien_Profile.php etc directly in a single folder itself.

In index.php below code is executed, which include file that define compilation path

$compilerConfig = MAGENTO_ROOT . '/includes/config.php';
if (file_exists($compilerConfig)) {
    include $compilerConfig;
}

Here is the /includes/conig.php file code that is included in above code:-

#define('COMPILER_INCLUDE_PATH', dirname(__FILE__).DIRECTORY_SEPARATOR.'src');

Now in Mage.php you can see that if compilation path is set than class are directly loaded from include/src folder

if (defined('COMPILER_INCLUDE_PATH')) {
    $appPath = COMPILER_INCLUDE_PATH;
    set_include_path($appPath . PS . Mage::registry('original_include_path'));
    include_once COMPILER_INCLUDE_PATH . DS . "Mage_Core_functions.php";
    include_once COMPILER_INCLUDE_PATH . DS . "Varien_Autoload.php";
} else {
    /**
     * Set include path
     */
    $paths = array();
    $paths[] = BP . DS . 'app' . DS . 'code' . DS . 'local';
    $paths[] = BP . DS . 'app' . DS . 'code' . DS . 'community';
    $paths[] = BP . DS . 'app' . DS . 'code' . DS . 'core';
    $paths[] = BP . DS . 'lib';
 
    $appPath = implode(PS, $paths);
    set_include_path($appPath . PS . Mage::registry('original_include_path'));
    include_once "Mage/Core/functions.php";
    include_once "Varien/Autoload.php";
}

9. What is the difference between resource model, collection, and model?

Model in Magento handles logical operation with the database. There are several kinds of model like
ActiveRecord/one-object-one-table Model, an Entity Attribute Value (EAV) Model. Each Model also gets a Model Collection.
A Magento model object contains a reference to a resource model, which interacts with the database on behalf of the “model”. It is the one who performs CRUD operation on the database.
Collection model contains code that fetched a group of model objects. On collection, we implement filtration and sorting kinds of features. Collection objects inherit from a different chain of classes than the normal resource models, It is also considered a resource model and is instantiated with the Mage::getResourceModel method.

10. What is the difference between a flat table and EAV model?

Though we have covered this in the first question of this page also but let’s discuss more of it. EAV is an entity attribute value database model, where data is fully in normalized form. In Eav model, each data value is stored in their respective data type table. Example, for a product, product ID is stored in catalog_product_entity_int table, product name in catalog_product_entity_varchar, product price in catalog_product_entity_decimal, product created date in catalog_product_entity_datetime and product description in catalog_product_entity_text table. EAV model is complex and thus slow as it joins several tables to retrieve even a simple information.

A flat model uses just one table, so it’s not normalized and thus it uses more database space. It is faster than EAV in retrieving information but it is not good for dynamic requirements where you may have to add more columns in a database table in future. It’s good when comes to performance, as it will only require one query to load whole product. Columns are called fields in flat model. Magento uses indexing process to manage data in flat tables for products so that frontend can be speed up.

Magento autoshipping according to lowest price

Recently one of my clients came up with a requirement to provide auto shipping on basis of price. He wanted to add shipping price automatically to customer cart as soon as customer adds a product to cart. So below is the code that I followed:-
Modules I know you all can create on your own, so we will be discuss about the Events on which I placed observer and observer functionality that adds shipping rates to our shopping cart so that lets go with config.xml first:-
Below are the events on which we have implemented our code.

<events>
            <checkout_cart_update_items_after>
                <observers>
                    <w3solver_autoshipping_observer>
                        <type>singleton</type>
                        <class>w3solver_autoshipping/observer</class>
                        <method>addShipping</method>
                    </w3solver_autoshipping_observer>
                </observers>
            </checkout_cart_update_items_after>
            <checkout_cart_product_add_after>
                <observers>
                    <w3solver_autoshipping_observer>
                        <type>singleton</type>
                        <class>w3solver_autoshipping/observer</class>
                        <method>addShipping</method>
                    </w3solver_autoshipping_observer>
                </observers>
            </checkout_cart_product_add_after>
            <sales_quote_remove_item>
                <observers>
                    <w3solver_autoshipping_observer>
                        <type>singleton</type>
                        <class>w3solver_autoshipping/observer</class>
                        <method>addShipping</method>
                    </w3solver_autoshipping_observer>
                </observers>
            </sales_quote_remove_item>
            <controller_action_postdispatch_checkout_cart_estimatePost>
                <observers>
                    <w3solver_autoshipping_observer>
                        <type>singleton</type>
                        <class>w3solver_autoshipping/observer</class>
                        <method>addShipping</method>
                    </w3solver_autoshipping_observer>
                </observers>
            </controller_action_postdispatch_checkout_cart_estimatePost>
            <customer_login>
                <observers>
                    <w3solver_autoshipping_observer>
                        <type>singleton</type>
                        <class>w3solver_autoshipping/observer</class>
                        <method>addShipping</method>
                    </w3solver_autoshipping_observer>
                </observers>
            </customer_login>      
        </events>

Another step is to have an observer file and write a functions that filter shipping rate according to price and auto add it to quote:-

<?php
class W3solver_AutoShipping_Model_Observer {

    public function addShipping($observer) {

        $checkout = Mage::getSingleton('checkout/session');
        $quote = $checkout->getQuote();
        $shippingAddress = $quote->getShippingAddress();

        //first use the default Country code
        $country = Mage::getStoreConfig('general/country/default');

        //check if the customer has logged in
        if (Mage::getSingleton('customer/session')->isLoggedIn()) {
            $customer = Mage::getSingleton('customer/session')->getCustomer();
            if ($customer->getPrimaryShippingAddress() && $customer->getPrimaryShippingAddress()->getCountry()) {

                //use customer's shipping address country if there's one
                $country = $customer->getPrimaryShippingAddress()->getCountry();
            }
        }

        //only set country if it does not exists already
        if (!$shippingAddress->getCountryId()) {
            $shippingAddress->setCountryId($country);
        }

        //allow shipping rates recalculation
        $shippingAddress->setCollectShippingRates(true);


        //rest qutoe item counts so that shipping calculation is based on the correct quantity
        $quote->collectTotals();

        $shippingAddress->collectShippingRates();

        if ($quote->getItemsCount()) {

            //get available rates
            $rates = $shippingAddress->getAllShippingRates();

            if (count($rates)) {

                /* sort rate by price */
                foreach ($rates as $i => $rate) {
		
                    $tmp[$i] = $rate->getPrice();
                }

                natsort($tmp);

                foreach ($tmp as $i => $price) {
                    $result[] = $rates[$i];
                }
                $rates = $result;

                //get the top positioned rate. It's based on the position set up in backend
                $topRate = reset($rates);
                $rateToApply = $topRate->getCode();

                try {

                    //apply shipping
                    $shippingAddress->setShippingMethod($rateToApply);
                    $quote->save();

                    //set checkoutstate to CHECKOUT_STATE_BEGIN
                    //prevent the address from being removed when init() in Mage_Checkout_Model_Cart is called 
                    $checkout->resetCheckout();
                } catch (Mage_Core_Exception $e) {
                    $checkout->addError($e->getMessage());
                } catch (Exception $e) {
                    $checkout->addException($e, Mage::helper('checkout')->__('Cannot set shipping method.'));
                    Mage::logException($e);
                }
            }
        }

        return $this;
    }

}

I hope that above code will help you, just drop in your comments if you find any issue or if you have any suggestion.

Magento Interview Question Part-1

I have been interviewing in Magento from last three years and also given several ;). Below I am sharing my experience and also basic Magento question that interviewer frequently asked.

1. What is Magento?
Well nobody will ask you this silly question, but just to start let’s discuss this. It is an open source e-commerce platform, enriched with lots of functionality and it has a very strong catalog management system which is unbeatable by any other platform in a market.

2. What is code pool in Magento? How many types of they are?
Most basic which every Magento developer know, Magento has provided a different section to for writing up your module and provided different significance to them, basically, three code pools are there: core, local and community.
Below is the Purpose of different code pool:-
Core :- Magento core developer code is placed here. We never place our code in core code pool, neither make any changes over here.
Local :- Magento developer who make their own module or customized Magento default functionality place their code here.
Community :- When we download an extension from Magento community then we normally place extension here.

There is a sequence in which Magento calls these code pool. Suppose the same file is overridden in local and community then local is always given preference. As it can be seen in Mage.php line 43

    $paths = array();
    $paths[] = BP . DS . 'app' . DS . 'code' . DS . 'local';
    $paths[] = BP . DS . 'app' . DS . 'code' . DS . 'community';
    $paths[] = BP . DS . 'app' . DS . 'code' . DS . 'core';
    $paths[] = BP . DS . 'lib';

Above code clearly tells that firstly local, then community, then core code pool will be executed. Thus when we override our file we place them mostly under local code pool.

3. What are routers in Magento and tell the sequence in which they are called?
Magento uses a front controller which instantiate router object and router object check the request URL for the match with controller and action. Thus routers are responsible for routing a request in Magento. Magento uses four type of router and they are called in below sequence:-
Mage_Core_Controller_Varien_Router_Admin
Mage_Core_Controller_Varien_Router_Standard
Mage_Cms_Controller_Router
Mage_Core_Controller_Varien_Router_Default

Code can be seen in Mage_Core_Controller_Varien_Front class on line 169 in dispatch() function

while (!$request->isDispatched() && $i++ < 100) { foreach ($this->_routers as $router) {
                /** @var $router Mage_Core_Controller_Varien_Router_Abstract */
                if ($router->match($request)) {
                    break;
                }
            }
        }

A loop is executed maximum 100 times for each request if it does not fall under any router and request are matched will all router sequentially.

4. How can we enhance the Magento performance?
This question has vast options to answer with, your practical knowledge can provide a better answer but below are some steps that we do take before moving our web application to a production environment to speed up Magento.
Disable the Magento log (Writing up log might take some time thus disabling then helps in speeding up but you will then not be able to find out the reason of certain issue. In that case forced log option helps)
Disable any unused modules(we should take care not to enable any unused module as it will then be an overhead on Magento because config of that module will always be taken care of)
Magento Caching
Enable Gzip compression
Optimize your image
Optimize your Server
Use a Content Delivery Network (CDN)
USE Gzip Components
Put Stylesheets at the Top (CSS Files in head tag). Also, there is an option to merge all your stylesheet and JS file into single file to reduce HTTP request.
Put Scripts at the Bottom (JS files in footer)
Avoid CSS Expressions (100/2) Minor but can be taken care of.

5. What technology does Magento use?
This could be the silliest question that can be asked from a fresher. Well, Magento uses PHP for programming and MYSQL for database.

6. List different design pattern that Magento use?
This is a very known question for Magento people. Magento follows several types of design pattern such as:-
Singleton Pattern
Factory Pattern
Front Controller Pattern
Registry Pattern
Event Observer Pattern
Prototype Pattern
Object Pool Pattern
Iterator Pattern
Lazy Loading Pattern
Module pattern

7. Describe Singleton and factory pattern. what is the difference between them and how does Magento uses them?
The Singleton pattern is responsible for instantiating a class but it first verifies that if an object of that class is already instantiated or not, if yes then it will return an already created object. On the other side, Factory pattern is also responsible for factorizing (instantiating) classes. It’s widely used throughout the Magento and leverages the autoloading system in Magento. By defining an alias in module config.xml file we are letting the factory know where it can find classes.
For using singeleton pattern we uses Mage::getSingleton(“class alias”); mainly we use it for customer/session, core/session
For using factory pattern we have Mage::getModel(“class alias”);

getSingleton and getModel function definition is found in Mage.php

8. what is the difference between using $this->__(“any text”) and Mage::helper(‘catalog’)->(“any text)?
Well, both works similarly and get the text from a language file. But Mage::helper(‘catalog’)->(“any text”) make sure that specific helper will be used for translation. For example,
Suppose we have a class Mage_Adminhtml_Block_Catalog_Product_Grid_Block
Now, for column header we have,
“header” => Mage::helper(“catalog”->__(“Name”)
So if we will not specify catalog here then adminhtml helper will be considered.

Also, suppose we override some file then also issue can come. For example we have class Mage_Catalog_Block_Breadcrumbs and there is code Mage::helper(“catalog”)->__(“Home”)
Now we override namespace_Modulename_Block_Breadcrumb
if $this->__(“Home”) was used then “Modulename” was used.

9. What is lazy loading?
In Magento Lazy loading is mainly used in ORM or in DATA Mapper, as the name suggest it delays loading of an object until object is called upon. In magento lazy loading is mainly utilized with data not objects.
For example, we heavily uses collection in Magento and we have below code:-

       $collection = Mage::getModel('catalog/product')->getCollection()
            ->addAttributeToSelect('name')
            ->addAttributeToSelect('sku')
            ->addAttributeToSelect('price')
            ->addStoreFilter($this->getRequest()->getParam('store'))
            ->joinField('position',
                'catalog/category_product',
                'position',
                'product_id=entity_id',
                'category_id='.(int) $this->getRequest()->getParam('id', 0),
                'left');
        $this->setCollection($collection);

Above code is just setting or making a query for the database but it is not actually interacting with DB until we actually want to get the data. So if we use $collection->getData() then the collection will interact with database, so it has delays the loading of data.

10. What are getter/setter methods and how does Magento uses them?
PHP has certain magic methods which are called automatically according to their implementation. For example,
__call() :- This method is called automatically when PHP cannot find a method which is called somewhere.

In lib/varien/object.php we have defined this method

public function __call($method, $args)
    {
        switch (substr($method, 0, 3)) {
            case 'get' :
                //Varien_Profiler::start('GETTER: '.get_class($this).'::'.$method);
                $key = $this->_underscore(substr($method,3));
                $data = $this->getData($key, isset($args[0]) ? $args[0] : null);
                //Varien_Profiler::stop('GETTER: '.get_class($this).'::'.$method);
                return $data;

            case 'set' :
                /* Some code here */
            case 'uns' :
                /* Some code here */

            case 'has' :
                /* Some code here*/
        }
        throw new Varien_Exception("Invalid method ".get_class($this)."::".$method."(".print_r($args,1).")");
    }

So above you can see case that checks for ‘get’, ‘set’, ‘uns’ and ‘has’. These methods are called whenever Magento code calls any method which is not defined anywhere throughout the code. Now we knows that to fetch value of any field we use getdata(‘fieldname’) function and we also have another way getFieldName()
Now GetData() is a function that is found in lib/varien/object.php and will thus return us with required value but getFieldName() is not defined anywhere so __call will be called and as it can be seen above it will then get the method name and execute as per required functionality.

Magento add external URL to menu admin

I was just trying to add an external link on my admin menu panel and figured out that there is no direct option to add, we need to override some functionality to achieve this. So here is the solution I found out for the same. Unfortunately, we need to have a small module for this functionality:-

Firstly we need to overwrite the _buildMenuArray() function of Mage_Adminhtml_Block_Page_Menu class to add a condition for external url. So let’s start our modification:-

Create your config file to override the page menu class, as shown in below code:

<config>
    <modules>
        <W3solver_Menulink>
            <version>1.0.0</version>
        </W3solver_Menulink>
    </modules>
	
    <global>
        <blocks>
            <adminhtml>
                <rewrite>
                    <page_menu>W3solver_Menulink_Block_Adminhtml_Page_Menu</page_menu>
                </rewrite>
            </adminhtml>
        </blocks>
        <helpers>
            <menulink>
                <class>W3solver_Menulink_Helper</class> 
            </menulink>
        </helpers>
    </global>
</config>

Add a block file to override page menu, review line 40 for the modification:-

class W3solver_Menulink_Block_Adminhtml_Page_Menu extends Mage_Adminhtml_Block_Page_Menu {
    
    /**
     * Recursive Build Menu array
     *
     * @param Varien_Simplexml_Element $parent
     * @param string $path
     * @param int $level
     * @return array
     */
    protected function _buildMenuArray(Varien_Simplexml_Element $parent=null, $path='', $level=0)
    {
        if (is_null($parent)) {
            $parent = Mage::getSingleton('admin/config')->getAdminhtmlConfig()->getNode('menu');
        }

        $parentArr = array();
        $sortOrder = 0;
        foreach ($parent->children() as $childName => $child) {
            if (1 == $child->disabled) {
                continue;
            }

            $aclResource = 'admin/' . ($child->resource ? (string)$child->resource : $path . $childName);
            if (!$this->_checkAcl($aclResource) || !$this->_isEnabledModuleOutput($child)) {
                continue;
            }

            if ($child->depends && !$this->_checkDepends($child->depends)) {
                continue;
            }

            $menuArr = array();

            $menuArr['label'] = $this->_getHelperValue($child);

            $menuArr['sort_order'] = $child->sort_order ? (int)$child->sort_order : $sortOrder;

            /* condition added to manage external url*/
            if ($child->external_url) {
                $menuArr['url'] = (string)$child->external_url;
            } else if ($child->action) {
                $menuArr['url'] = $this->_url->getUrl((string)$child->action, array('_cache_secret_key' => true));
            } else {
                $menuArr['url'] = '#';
                $menuArr['click'] = 'return false';
            }

            $menuArr['active'] = ($this->getActive()==$path.$childName)
                || (strpos($this->getActive(), $path.$childName.'/')===0);

            $menuArr['level'] = $level;

            if ($child->children) {
                $menuArr['children'] = $this->_buildMenuArray($child->children, $path.$childName.'/', $level+1);
            }
            $parentArr[$childName] = $menuArr;

            $sortOrder++;
        }

        uasort($parentArr, array($this, '_sortMenu'));

        while (list($key, $value) = each($parentArr)) {
            $last = $key;
        }
        if (isset($last)) {
            $parentArr[$last]['last'] = true;
        }

        return $parentArr;
    }

 

Here is code of my menu:-

<config>
    <menu>
        <menulink translate="title" module="menulink">
            <title>Menu Link</title>
            <sort_order>400</sort_order>
            <children>
                <menulink translate="title" module="menulink">
                    <title>Menu Link</title>
                    <sort_order>1</sort_order>
                    <external_url>http:www.google.com</external_url>
                </menulink>
            </children>
        </menulink>
    </menu>
</config>

Just put down your comment if you face any issue.