16
MAGENTO BEST PRACTICES ALESSANDRO RONCHI MANCHESTER, NOV. 7 th 2015

A true story about Magento best practices

Embed Size (px)

Citation preview

MAGENTO BEST PRACTICESALESSANDRO RONCHI

MANCHESTER, NOV. 7th 2015

ABOUT ME: @aleron75

aleron75/mageres

#magebp 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

#magebp 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

#magebp 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

#magebp 6/16Based on a real story...

What you will be shown is real code that run on production.

This code was written to displaya category navigation menu.

No animals were harmed in the making of this code; a website was.

#magebp 7/16

First chunkseek 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...

}

#magebp 8/16

First chunkseek 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

#magebp 9/16

Second chunkseek 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()));

    }

  }

}

#magebp 10/16

Second chunkseek 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?

#magebp 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.

#magebp 12/16

Refactoring first chunkseek 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...

}

#magebp 13/16

Refactoring second chunkseek 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);

    }

  }

}

#magebp 14/16

Comparison(using XHProf)

Before refactoring

After refactoring 10x faster!

#magebp 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

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