Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

A true story about Magento best practices

5,021 views

Published on

Slides taken from my MageTitans presentation at Manchester, November 7th 2015

Published in: Software
  • Be the first to comment

A true story about Magento best practices

  1. 1. MAGENTO BEST PRACTICES ALESSANDRO RONCHI MANCHESTER, NOV. 7th 2015
  2. 2. ABOUT ME: @aleron75 aleron75/mageres
  3. 3. #m agebp 3/16#magebp rules ● Use the best available tools ● Use Magento runtime ● Use alternatives to Mage::log() ● Extend native autoloading ● Write effective and solid MVC components ● Write scalable code ● Never touch the core
  4. 4. #m agebp 4/16#magebp example ● Use the best available tools ● Use Magento runtime ● Use alternatives to Mage::log() ● Extend native autoloading ● Write effective and solid MVC components ● Write scalable code ● Never touch the core
  5. 5. #m agebp 5/16#magebp example ● Use the best tools & habits – to test code – to profile code ● Use Magento runtime – to validate code easily and rapidly ● Write scalable code – to avoid performance traps
  6. 6. #m agebp 6/16Based on a real story... What you will be shown is real code that run on production. This code was written to display a category navigation menu. No animals were harmed in the making of this code; a website was.
  7. 7. #m agebp 7/16 First chunk seek for category subcategories $rootCatID = Mage::app()­>getStore()­>getRootCategoryId(); $cat = Mage::getModel('catalog/category')­>load($rootCatID); $subCats = $cat­>getChildren(); foreach (explode(',', $subCats) as $subCatid) {   $category = Mage::getModel('catalog/category')     ­>load($subCatid);   $subcategories = $category­>getChildren(); } foreach (explode(',', $subcategories) as $subCategoryid) {   $subcategory = Mage::getModel('catalog/category')     ­>load($subCategoryid);   // Second chunk... }
  8. 8. #m agebp 8/16 First chunk seek for category subcategories $rootCatID = Mage::app()­>getStore()­>getRootCategoryId(); $cat = Mage::getModel('catalog/category')­>load($rootCatID); $subCats = $cat­>getChildren(); foreach (explode(',', $subCats) as $subCatid) {   $category = Mage::getModel('catalog/category')     ­>load($subCatid);   $subcategories = $category­>getChildren(); } foreach (explode(',', $subcategories) as $subCategoryid) {   $subcategory = Mage::getModel('catalog/category')     ­>load($subCategoryid);   // Second chunk... } Assuming there is only one sub category will break menu as soon as a new one is added: and it happened! Loading in loops doesn't scale
  9. 9. #m agebp 9/16 Second chunk seek for product categories foreach (explode(',', $subcategories) as $subCategoryid) {   $subcategory = Mage::getModel('catalog/category')­>load($subCategoryid);   $category = Mage::getModel('catalog/category')     ­>load($subcategory­>getId());   $subcatProducts = Mage::getModel('catalog/product')     ­>getCollection()     ­>addCategoryFilter($subcategory)­>load();   foreach($subcatProducts as $product) {     foreach($product­>getCategoryIds() as $categoryId) {       $myCategory = Mage::getModel('catalog/category')­>load($categoryId);       $catUrl = $myCategory­>getUrl();       $prodUrlKey = end($explode("/", $product­>getProductUrl()));     }   } }
  10. 10. #m agebp 10/16 Second chunk seek for product categories foreach (explode(',', $subcategories) as $subCategoryid) {   $subcategory = Mage::getModel('catalog/category')­>load($subCategoryid);   $category = Mage::getModel('catalog/category')     ­>load($subcategory­>getId());   $subcatProducts = Mage::getModel('catalog/product')     ­>getCollection()     ­>addCategoryFilter($subcategory)­>load();   foreach($subcatProducts as $product) {     foreach($product­>getCategoryIds() as $categoryId) {       $myCategory = Mage::getModel('catalog/category')­>load($categoryId);       $catUrl = $myCategory­>getUrl();       $prodUrlKey = end($explode("/", $product­>getProductUrl()));     }   } } $category is not used and adds another load in a loop! WHY?
  11. 11. #m agebp 11/16 There is a name for this... Code Running Ashamedly on Production Sadly enough a customer paid for that: it's unethical other than unprofessional. This is not technical debt. This is building with sand.
  12. 12. #m agebp 12/16 Refactoring first chunk seek for category subcategories $configuredCatId =  Mage::getStoreConfig('my/own/path'); $category = Mage::getModel('catalog/category')   ­>getCollection()   ­>addIdFilter($configuredCatId)   ­>setPageSize(1)   ­>getFirstItem(); $subcategories = $category­>getChildrenCategories(); foreach ($subcategories as $subcategory) {   // Second chunk... }
  13. 13. #m agebp 13/16 Refactoring second chunk seek for product categories foreach ($subcategories as $subcategory) {   $subcatProducts = $subcategory­>getProductCollection();   foreach($subcatProducts as $product) {     $productCategories = $product­>getCategoryCollection();     foreach($productCategories as $myCategory) {       $catUrl = $myCategory­>getUrl();       $prodUrl = $product­>getProductUrl();       $prodUrlKey = substr(strrchr($prodUrl, '/'), 1);     }   } }
  14. 14. #m agebp 14/16 Comparison (using XHProf) Before refactoring After refactoring 10x faster!
  15. 15. #m agebp 15/16 Refactoring (using tests) ● Testing gives us the confidence to change code without breaking functionality ● Testing doesn't require complex tools – start from manual tests – automate to scale – start from common tools: diff – use more sophisticated tools when needed
  16. 16. THANK YOU! https://github.com/aleron75https://github.com/aleron75 https://twitter.com/aleron75https://twitter.com/aleron75 http://leanpub.com/magebp/c/mt15ukhttp://leanpub.com/magebp/c/mt15uk

×