Magento is an E-commerce platform that allows rapid implementation of online stores and which comes with number of tools for a better online store management. However the quality of implementation depends on developer. A simple mistakes can lead to performance bottlenecks and code performance issues can have immediate critical impact to the business. This article provides a high-level overview of the most common mistakes that developers make while building an e-commerce store and issue that can impact performance & scalability etc of the Magento PHP code.
Developers often load Magento models in a loop to process some of the products properties. Below is an example of how they iterate over the array of product IDs to load a product model and process it in the loop:
foreach ($this->getProductIds() as $productId) { $product = Mage::getModel('catalog/product')->load($productId); $this->processProduct($product); }
Since Magento uses entity attribute value (EAV) model, loading an entity requires several heavy queries to execute. As the number of executed queries is multiplied with the number of products, we get extremely inefficient and slow code. Instead of loading products in a loop, a Magento data collection can help to load a set of models in a very efficient manner. The following example filters the result set of a collection by an array of product IDs and adds all requested product fields to result:
$collection = Mage::getResourceModel('catalog/product_collection')->addFieldToFilter('entity_id',array($this->getProductIds()))->addAttributeToSelect(array('name')); foreach ($collection as $product) { $this->processProduct($product); }
Developers sometimes do not consider that model load operation is not internally cached, and each time the load() method is called, one or more queries are ran against the database. Loading the same model several times causes noticeable performance degradation. For example:
$name = Mage::getModel('catalog/product')->load($productId)->getName(); $sku = Mage::getModel('catalog/product')->load($productId)->getSku(); $attr = Mage::getModel('catalog/product')->load($productId)->getAttr();
Each model should be loaded only once (if there is a reason to load it at all) to optimize performance:
$product = Mage::getModel('catalog/product')->load($productId); $name = $product->getName(); $sku = $product->getSku(); $attr = $product->getAttr();
Another point to consider is that sometimes it is not even necessary to load the model because you don’t need to work with model entity itself. The following code loads a product merely to get the product ID:
$product = Mage::getModel('catalog/product')->loadByAttribute('sku', $sku); $res['id'] = $product->getId();
In this case you can use the native product method getIdBySku() that will work much faster:
$res['id'] = Mage::getModel('catalog/product')->getIdBySku($sku);
Redundant data set utilization
A common mistake made by inexperienced Magento developers is to retrieve the complete collection of data, when only a limited number of items are required.
public function getRandomItem() { $collection = Mage::getResourceModel('mymodule/my_collection')->setRandomOrder(); return $collection->getFirstItem(); }
Always remember to apply a limitation to every collection query when retrieving one or more items. Below is an example of a collection query:
public function getRandomItem() { $collection = Mage::getResourceModel('mymodule/my_collection')>setRandomOrder()->setPageSize(1); return $collection->getFirstItem(); }
Sometimes developers want to retrieve the number of items in a particular collection, without further processing of its items. It such cases most of them use $collection->count() or count($collection) constructs, which appear to be obvious and natural solutions. However, it is most definitely the wrong way, because all the items of the collection will be loaded from the database and iterated. It is much more efficient to call the $collection->getSize() method instead.
Inefficient memory utilization
Using the database adapter method fetchAll() to fetch large result sets will cause a heavy demand on system and possibly network resources. Magento developers often fetch and iterate result sets as follows:
$rowSet = $this->_getReadAdapter()->fetchAll($select); foreach ($rowSet as $row) { //process row }
On large amounts of fetched data, this code will execute for a very long time and PHP will probably run out of memory. In the following example, each database row is fetched separately using the fetch() method to reduce resource consumption:
$query = $this->_getReadAdapter()->query($select); while ($row = $query->fetch()) { //process row }
The database server will execute only one query and the database buffer will be used for retrieving records one by one.
Developers often miss the basic PHP code optimization techniques. For example inefficient use of count() function in a for loop.
for ($i = 0; $i < count($rows); $i++) { //some code }
Although count() is fairly fast in regular use, this changes rapidly when it is used in a loop. If the array or collection $rows contains a lot of data, this code is slowed down significantly. Because the PHP interpreter doesn’t perform loop-invariant code motion automatically, a much better way is to move the count() call outside the loop:
$rowNum = count($rows); for ($i = 0; $i < $rowNum; $i++) { //some code }
Generally developers are given a short timeline to build or customize a Magento store. As a result few developers attempt to modify Magento core files as a quick solution to customer customization requirements. This type of patchwork development will have long term effects on the e-commerce website, since it will interfere with future Magento upgrades. One should always keep Magento core files protected for future upgrades. The best way to modify core files is to create your own module and override Model,Controller,Block etc using Magento’s class rewrite techniques. The easiest way to modify core files is to create a copy of the same folder structure in a local module folder as shown on the example below: e.g.: To modify
app/code/core/Mage/Checkout/controllers/OnepageController.php
Copy the complete folder structure to
app/code/local/Mage/Checkout/controllers/OnepageController.php
Always install latest security patches from Magento. Ignoring security patches can result in serious security threats. You can download latest security patches from Magento official website.
On numerous occasions developers copy and paste standard XML from the internet and create a module that ends up receiving errors. For example, if your module doesn’t require an admin router, then you should not leave the admin router in the folder. Based on SUPEE-6788 patch released by Magento team, use new method to specify admin routers in confi.xml.
Old Method – won’t work after installing security patch – SUPEE-6788
<admin> <routers> <mymodule> <use>admin</use> <args> <module>Pits_Mymodule</module> <frontName>pits_mymodule</frontName> </args> </mymodule> </routers> </admin>
New Method
<admin> <routers> <adminhtml> <args> <modules> <pits_mymodule after="Mage_Adminhtml">Pits_Mymodule_Adminhtml</pits_mymodule> </modules> </args> </adminhtml> </routers> </admin>
Always use Magento Designer guides to style Magento Websites. Since Magento has great theme fallback system there is really no need to touch default theme.
Although easiest way to make new theme for new Magento is top copy the whole theme to a new folder, don’t do that.
Copy only the files you will need:from /design/frontend/default/default/ directory to /design/frontend/default/YOUR_NEW_THEME directory.
Do the same thing with /skin/frontend/default/default/. You can apply new theme under System/Configuration/Design.If you copy entire theme folder to create new theme, future upgrades will be a difficult task for you as you have to upgrade entire theme files.
One thing Magento PHP developers should keep in mind: Always be attentive to performance-critical code, avoid useless computations inside loops, try to learn and understand the features of the framework, and use them correctly. If you’re dealing with small data volumes you may not care too much about code optimization. Use common sense—sometimes it is acceptable to fetch all data or process it in a loop, but always think ahead and consider how your code will perform and scale in the future. Magento developers often copy and paste Magento codes snippets from internet, that may be inefficient for that particular scenario resulting in performance bottlenecks and even some errors. So it is advisable to use only standard documentations.
source: http://info.magento.com/rs/magentocommerce/images/ Conquer_the_5_Most_Common_Magento_Coding_Issues_to_Optimize_Your_Site_for_Performance.pdf
You must be logged in to post a comment.