Magento Best Practices - 1/53 Meet Magento IT – March 5th-6th, 2015
Magento Best Practices
“there are at least two ways of developing things in Magento
the best of which is usually the third”
- Alessandro Ronchi -
Magento Best Practices - 2/53 Meet Magento IT – March 5th-6th, 2015
Magento Best Practices
“there are at least two ways of developing things in Magento
the best of which is usually the third”
Magento Best Practices - 3/53 Meet Magento IT – March 5th-6th, 2015
About me
● Long term Magento Developer
– 6+ years full-time work on Magento
– 2+ years MCD
● Active Community member
– 10+ free extensions
– PUG MoRe main founder and coordinator
– Organizer of Mageday 2013 and 2014
Magento Best Practices - 4/53 Meet Magento IT – March 5th-6th, 2015
About this talk
It's a dense technical talk:
● mainly focused on Magento 1
● some concepts are also valid for Magento 2
● development experience required
Magento Best Practices - 5/53 Meet Magento IT – March 5th-6th, 2015
About you
● Developers?
● Programmers?
● Coders?
● What else?
Magento Best Practices - 6/53 Meet Magento IT – March 5th-6th, 2015
Who we should aim to be
Software craftsmen
“Bad code can function but can bring an organization to its knees.”
“Craftsmanship comes from values that drive disciplines.” - R. Martin
“I’m just a good programmer with great habits.” - K. Beck
“Try to refactor code so that comment becomes superfluous.” - M. Fowler
Magento Best Practices - 7/53 Meet Magento IT – March 5th-6th, 2015
Tools
There are a lot of tools which
support and improve the
development process
“9. Do you use the best tools money can buy?” - The Joel Test
Magento Best Practices - 8/53 Meet Magento IT – March 5th-6th, 2015
Tools
●
Effective IDEs (PhpStorm, Zend Studio)
●
Magicento (for PhpStorm) by Enrique Piatti
●
Commerce Bug by Alan Storm
●
n98-magerun by Christian Münch
●
Modman by Colin Mollenhour
●
Composer by Jordi Boggiano
●
Ultimate Module Creator by Marius Strajeru
●
Magento Code Sniffer Coding Standard by Magento ECG
●
Magento Project Mess Detector by Fabrizio Branca
●
Judge by Netresearch App Factory
●
Triplecheck.io by Allan MacGregor
Magento Best Practices - 9/53 Meet Magento IT – March 5th-6th, 2015
Tools: n98-magerun
● De facto standard command line toolkit to
work with Magento
● Is also very useful to automate deployment
tasks
● Extensible via plugins
● Available reference book by Alan Storm
https://leanpub.com/command-line-magento
Magento Best Practices - 10/53 Meet Magento IT – March 5th-6th, 2015
Magento Runtime
Why
● to check code inside a full initialized
Magento application
How
● Write a Module (slow)
● Write a Shell Script (faster)
● Use bash snippet (fastest)
Magento Best Practices - 11/53 Meet Magento IT – March 5th-6th, 2015
Magento Runtime: Shell Script
● Extend Mage_Shell_Abstract
● Set proper store scope
protected $_appCode = 'admin';
● Override _applyPhpVariables()
● Load app area in _construct()
– Mage_Core_Model_App_Area::AREA_FRONTEND
– Mage_Core_Model_App_Area::AREA_ADMINHTML
Magento Best Practices - 12/53 Meet Magento IT – March 5th-6th, 2015
Magento Runtime: bash snippet
<?php
if (isset($_SERVER['REQUEST_METHOD'])) {
  die('Permission denied.'); // Prevent HTTP access
} 
set_time_limit(0); // Avoid any time limit
ini_set('memory_limit', ­1); // Avoid any memory limit
require_once 'app/Mage.php'; // Include base class
Mage::setIsDeveloperMode(true); // Enable developer mode
umask(0); // Set the default file creation mask
Mage::app(); // Init application with default store
Magento Best Practices - 13/53 Meet Magento IT – March 5th-6th, 2015
Magento Runtime: ready snippets
Customer
https://gist.github.com/aleron75/190b25ea621c14a21d6b
Administrator
https://gist.github.com/aleron75/9d6609e99153d19461f3
Magento Best Practices - 14/53 Meet Magento IT – March 5th-6th, 2015
Logging
Don't use static Mage::log()
A static method is a dependency:
a hidden relation which increases
coupling between classes
Magento Best Practices - 15/53 Meet Magento IT – March 5th-6th, 2015
Logging: Log Adapter
/** @var Mage_Core_Model_Log_Adapter $logger */
$logger = Mage::getModel(
  'core/log_adapter', 
  'my_log_file_name.log');
$logger­>log("Hello World");
Magento Best Practices - 16/53 Meet Magento IT – March 5th-6th, 2015
Logging: Log Adapter
Pros
● No more Mage::log() dependency
● Log file name specified once
Cons
● Fixed severity for debug messages
● Logs always - regardless of config
Magento Best Practices - 17/53 Meet Magento IT – March 5th-6th, 2015
Logging: Logger Model
/** @since Version 1.8.x */
/** @var Mage_Core_Model_Logger $logger */
$logger = Mage::getModel('core/logger');
$logger­>log("Hello World");
$logger­>logException(new Exception('Error'));
Magento Best Practices - 18/53 Meet Magento IT – March 5th-6th, 2015
Logging: Logger Model
Pros
● No more Mage::log() dependency
● No limitations on severity
● Doesn't always force logs
Cons
● Log file name specified always
Magento Best Practices - 19/53 Meet Magento IT – March 5th-6th, 2015
Logging: custom
Implement only pros:
● No more Mage::log() dependency
● No limitations on severity
● Doesn't always force logs
● Log file name specified once
Magento Best Practices - 20/53 Meet Magento IT – March 5th-6th, 2015
Logging: custom
Custom log wrapper
https://github.com/aleron75/magelog
Monolog wrapper
https://github.com/aleron75/magemonolog
Magento Best Practices - 21/53 Meet Magento IT – March 5th-6th, 2015
Autoloading
Magento’s autoloader is registered at
the very beginning of framework's
bootstrap: it is difficult (not impossible)
to extend
It's not natively PSR−0 compliant
(PHP-FIG's birth follows Magento's)
Magento Best Practices - 22/53 Meet Magento IT – March 5th-6th, 2015
The Magento-PSR-0-Autoloader
extension registers an additional
autoloader which gives the ability to
include libraries adhering to PSR−0
Autoloading Standard (i.e.: Monolog)
Autoloading: enable PSR-0
Magento Best Practices - 23/53 Meet Magento IT – March 5th-6th, 2015
Effective MVC
MVC is a good example
of separation of concerns principle
That doesn't mean we don't have to
pay attention to avoid messing up
things anyway
Magento Best Practices - 24/53 Meet Magento IT – March 5th-6th, 2015
Effective MVC: Models
A Model is the entity which describes
the problem we want to solve in terms
of states and business logic
Magento Best Practices - 25/53 Meet Magento IT – March 5th-6th, 2015
Effective MVC: Models
● Keep Models simple and focused on a
single concern
● Choose the least visibility scope for
methods and declare classes final
● Prefer composition over inheritance (as
far as possible)
Magento Best Practices - 26/53 Meet Magento IT – March 5th-6th, 2015
Effective MVC: Models
Benefits of keeping Models simple:
● fewer reasons to change
● easier to upgrade
● easier to test
● clean interface
● smaller method signatures
Magento Best Practices - 27/53 Meet Magento IT – March 5th-6th, 2015
Effective MVC: Blocks & Templates
Blocks are responsible for
presentation data logic
Templates are responsible for
presentation logic
Magento Best Practices - 28/53 Meet Magento IT – March 5th-6th, 2015
Effective MVC: Blocks & Templates
Prefer single points of definition:
● No direct data/config access in Blocks;
use Models and Helpers instead
● Delegate to children Blocks whenever possible
(i.e.: Mage_Catalog_Block_Product_Price)
● Templates should only interact with their Blocks
● Enable cache on custom Blocks
Magento Best Practices - 29/53 Meet Magento IT – March 5th-6th, 2015
Effective MVC: Controllers
“a Controller accepts input and
converts it to commands for the Model
or View” - Wikipedia
Controllers manage application flow
Magento Best Practices - 30/53 Meet Magento IT – March 5th-6th, 2015
Effective MVC: Controllers
● Check user input is well-formed
i.e.: 16 digits required for a MasterCard number
● Don't perform business domain checks
i.e.: whether a MasterCard number is authorized
Magento Best Practices - 31/53 Meet Magento IT – March 5th-6th, 2015
Effective MVC: Helpers
They are not waste baskets :)
● utility methods containers
(Core Helpers represent a very good example)
● shouldn't implement logic.
For complex logic use service
Models
@see Mage_Sales_Model_Service_Quote
Magento Best Practices - 32/53 Meet Magento IT – March 5th-6th, 2015
Working with Data
Adopting best practices can avoid
unexpected performance
downgrade or behaviour.
Simply put: write scalable code
Magento Best Practices - 33/53 Meet Magento IT – March 5th-6th, 2015
Working with Data: EAV and Flat
● Flat is never used for EAV entities in
Admin Panel
● load() method always performs
joins on EAV tables
● Flat for EAV entities is only used for
Collections (unless filtering on non-
flat attributes)
Magento Best Practices - 34/53 Meet Magento IT – March 5th-6th, 2015
Working with Data: Products
Don't try this at home:
$products = Mage::getModel('catalog/product')
  ­>getCollection();
foreach ($products as $prod) {
  $prod­>load($prod­>getId()); # doesn't scale!
  echo $prod­>getDescription();
}
Magento Best Practices - 35/53 Meet Magento IT – March 5th-6th, 2015
Working with Data: Products
The following code is better for scalability:
$products = Mage::getModel('catalog/product')
  ­>getCollection()
  ­>addAttributeToSelect(array('description'));
foreach ($products as $prod) {
  echo $prod­>getDescription();
}
Magento Best Practices - 36/53 Meet Magento IT – March 5th-6th, 2015
Working with Data: Products
Comparison table*:
Load type # queries # joins Time Memory
In loop 875 1072 ~4 sec ~7 MB
Outside loop 8 1 ~0.4 sec ~2.5 MB
* on a development machine with official sample data
Magento Best Practices - 37/53 Meet Magento IT – March 5th-6th, 2015
Working with Data: Collection size
Comparison table*:
Count type Time Memory
count() ~0.966 sec ~25 MB
getSize() ~0.081 sec ~1.8 MB
* on a development machine with ~8000 products
Magento Best Practices - 38/53 Meet Magento IT – March 5th-6th, 2015
Working with Data: iterate Collection
Iterating: non-scalable approach
$products = Mage::getModel('catalog/product')
  ­>getCollection();
/** @var Mage_Catalog_Model_Product $product */
foreach ($products as $product) {
  // do something ­ lazy loading is triggered
}
Magento Best Practices - 39/53 Meet Magento IT – March 5th-6th, 2015
Working with Data: iterate Collection
Iterating: scalable approach
$products = Mage::getModel('catalog/product')
  ­>getCollection();
/** @var array $productData */
foreach ($products­>getData() as $productData) {
  // do something
}
Magento Best Practices - 40/53 Meet Magento IT – March 5th-6th, 2015
Working with Data: iterate Collection
Iterating: alternative scalable approach
$products = Mage::getModel('catalog/product')
  ­>getCollection();
/** @var Varien_Object $object */
while ($object = $products­>fetchItem()) {
  // do something
}
Magento Best Practices - 41/53 Meet Magento IT – March 5th-6th, 2015
Working with Data: iterate Collection
Comparison table*:
Fetch collection items Time Memory
standard ~1.913 sec ~25 MB
getData() ~0.017 sec ~1.3 MB
fetchItem() ~0.026 sec ~1.1 MB
* on a development machine with official sample data
Magento Best Practices - 42/53 Meet Magento IT – March 5th-6th, 2015
Working with Data: save attribute value
The following code takes ~1.5 seconds to
be executed on a development machine:
$product = Mage::getModel('catalog/product')
  ­>load(<existing_product_id>);
$product
  ­>setDataChanges(true) // force save
  ­>save();
Magento Best Practices - 43/53 Meet Magento IT – March 5th-6th, 2015
Working with Data: save attribute value
To save only some values a better approach is:
 
$product = Mage::getModel('catalog/product')
  ­>load(<existing_product_id>)
  ­>setName('New name')
  ­>setDescription('New description')
  ­>getResource()
  ­>saveAttribute($product, 'name')
  ­>saveAttribute($product, 'description');
Magento Best Practices - 44/53 Meet Magento IT – March 5th-6th, 2015
Working with Data: save attribute value
Comparison table*:
Save method Time Memory
save() ~1.5 sec ~5 MB
saveAttribute() ~0.02 sec a few KB
* on a development machine with official sample data
Magento Best Practices - 45/53 Meet Magento IT – March 5th-6th, 2015
Extending Magento
Never touch the core files!
Magento Best Practices - 46/53 Meet Magento IT – March 5th-6th, 2015
Extending Magento: monkey patch
Monkey patches are a (non upgrade safe) way to
change a core class without touching the
original file by copying it from the core code
pool to the local one.
Possible use cases:
● patching the core
● rapid prototyping
Magento Best Practices - 47/53 Meet Magento IT – March 5th-6th, 2015
Extending Magento: rewrites
Rewrites are the first step towards extending
Magento according to best practices.
Pros
● upgrade safe
Cons
● only one rewrite of same class → potential conflicts
● not compliant with the open/closed principle
Magento Best Practices - 48/53 Meet Magento IT – March 5th-6th, 2015
Extending Magento: events
Events represent the standard best way to
extend other classes behaviour.
Pros
● upgrade safe
● no conflicts: multiple observers on same event
Cons
● no event → no observer
Magento Best Practices - 49/53 Meet Magento IT – March 5th-6th, 2015
Extending Magento: interceptors
Interceptors are a way to change the behavior of
any public or protected method, by either
executing code before or after that method.
They are native on Magento 2 but can be also
added to Magento 1 thanks to:
https://github.com/danslo/Danslo_Aop
Magento Best Practices - 50/53 Meet Magento IT – March 5th-6th, 2015
Extending Magento: interceptors
Pros
● Upgrade safe
● No conflicts
● Any public/protected method can be
intercepted, no need of events
Cons
● Logic can be injected only at the beginning or
at the end, not in the middle of a method
Magento Best Practices - 51/53 Meet Magento IT – March 5th-6th, 2015
Conclusions
● Use the best available tools
● Use runtime outside Magento modules
● Don't use Mage::log()
● Extending autoloading is possible and useful
● Write effective and solid MVC components
● Data: write scalable code
● Never touch the core, prefer events to rewrites,
familiarize with interceptors
Magento Best Practices - 52/53 Meet Magento IT – March 5th-6th, 2015
The Handbook
https://leanpub.com/magebp
● If you liked this talk you'll
love the e-book :)
● Special 25% discount
code for you: mm15it
● Release date: ~June 2015
Magento Best Practices - 53/53 Meet Magento IT – March 5th-6th, 2015
Thank you!
QUESTIONS?
https://twitter.com/aleron75
https://github.com/aleron75

Magento best practices

  • 1.
    Magento Best Practices- 1/53 Meet Magento IT – March 5th-6th, 2015 Magento Best Practices “there are at least two ways of developing things in Magento the best of which is usually the third” - Alessandro Ronchi -
  • 2.
    Magento Best Practices- 2/53 Meet Magento IT – March 5th-6th, 2015 Magento Best Practices “there are at least two ways of developing things in Magento the best of which is usually the third”
  • 3.
    Magento Best Practices- 3/53 Meet Magento IT – March 5th-6th, 2015 About me ● Long term Magento Developer – 6+ years full-time work on Magento – 2+ years MCD ● Active Community member – 10+ free extensions – PUG MoRe main founder and coordinator – Organizer of Mageday 2013 and 2014
  • 4.
    Magento Best Practices- 4/53 Meet Magento IT – March 5th-6th, 2015 About this talk It's a dense technical talk: ● mainly focused on Magento 1 ● some concepts are also valid for Magento 2 ● development experience required
  • 5.
    Magento Best Practices- 5/53 Meet Magento IT – March 5th-6th, 2015 About you ● Developers? ● Programmers? ● Coders? ● What else?
  • 6.
    Magento Best Practices- 6/53 Meet Magento IT – March 5th-6th, 2015 Who we should aim to be Software craftsmen “Bad code can function but can bring an organization to its knees.” “Craftsmanship comes from values that drive disciplines.” - R. Martin “I’m just a good programmer with great habits.” - K. Beck “Try to refactor code so that comment becomes superfluous.” - M. Fowler
  • 7.
    Magento Best Practices- 7/53 Meet Magento IT – March 5th-6th, 2015 Tools There are a lot of tools which support and improve the development process “9. Do you use the best tools money can buy?” - The Joel Test
  • 8.
    Magento Best Practices- 8/53 Meet Magento IT – March 5th-6th, 2015 Tools ● Effective IDEs (PhpStorm, Zend Studio) ● Magicento (for PhpStorm) by Enrique Piatti ● Commerce Bug by Alan Storm ● n98-magerun by Christian Münch ● Modman by Colin Mollenhour ● Composer by Jordi Boggiano ● Ultimate Module Creator by Marius Strajeru ● Magento Code Sniffer Coding Standard by Magento ECG ● Magento Project Mess Detector by Fabrizio Branca ● Judge by Netresearch App Factory ● Triplecheck.io by Allan MacGregor
  • 9.
    Magento Best Practices- 9/53 Meet Magento IT – March 5th-6th, 2015 Tools: n98-magerun ● De facto standard command line toolkit to work with Magento ● Is also very useful to automate deployment tasks ● Extensible via plugins ● Available reference book by Alan Storm https://leanpub.com/command-line-magento
  • 10.
    Magento Best Practices- 10/53 Meet Magento IT – March 5th-6th, 2015 Magento Runtime Why ● to check code inside a full initialized Magento application How ● Write a Module (slow) ● Write a Shell Script (faster) ● Use bash snippet (fastest)
  • 11.
    Magento Best Practices- 11/53 Meet Magento IT – March 5th-6th, 2015 Magento Runtime: Shell Script ● Extend Mage_Shell_Abstract ● Set proper store scope protected $_appCode = 'admin'; ● Override _applyPhpVariables() ● Load app area in _construct() – Mage_Core_Model_App_Area::AREA_FRONTEND – Mage_Core_Model_App_Area::AREA_ADMINHTML
  • 12.
    Magento Best Practices- 12/53 Meet Magento IT – March 5th-6th, 2015 Magento Runtime: bash snippet <?php if (isset($_SERVER['REQUEST_METHOD'])) {   die('Permission denied.'); // Prevent HTTP access }  set_time_limit(0); // Avoid any time limit ini_set('memory_limit', ­1); // Avoid any memory limit require_once 'app/Mage.php'; // Include base class Mage::setIsDeveloperMode(true); // Enable developer mode umask(0); // Set the default file creation mask Mage::app(); // Init application with default store
  • 13.
    Magento Best Practices- 13/53 Meet Magento IT – March 5th-6th, 2015 Magento Runtime: ready snippets Customer https://gist.github.com/aleron75/190b25ea621c14a21d6b Administrator https://gist.github.com/aleron75/9d6609e99153d19461f3
  • 14.
    Magento Best Practices- 14/53 Meet Magento IT – March 5th-6th, 2015 Logging Don't use static Mage::log() A static method is a dependency: a hidden relation which increases coupling between classes
  • 15.
    Magento Best Practices- 15/53 Meet Magento IT – March 5th-6th, 2015 Logging: Log Adapter /** @var Mage_Core_Model_Log_Adapter $logger */ $logger = Mage::getModel(   'core/log_adapter',    'my_log_file_name.log'); $logger­>log("Hello World");
  • 16.
    Magento Best Practices- 16/53 Meet Magento IT – March 5th-6th, 2015 Logging: Log Adapter Pros ● No more Mage::log() dependency ● Log file name specified once Cons ● Fixed severity for debug messages ● Logs always - regardless of config
  • 17.
    Magento Best Practices- 17/53 Meet Magento IT – March 5th-6th, 2015 Logging: Logger Model /** @since Version 1.8.x */ /** @var Mage_Core_Model_Logger $logger */ $logger = Mage::getModel('core/logger'); $logger­>log("Hello World"); $logger­>logException(new Exception('Error'));
  • 18.
    Magento Best Practices- 18/53 Meet Magento IT – March 5th-6th, 2015 Logging: Logger Model Pros ● No more Mage::log() dependency ● No limitations on severity ● Doesn't always force logs Cons ● Log file name specified always
  • 19.
    Magento Best Practices- 19/53 Meet Magento IT – March 5th-6th, 2015 Logging: custom Implement only pros: ● No more Mage::log() dependency ● No limitations on severity ● Doesn't always force logs ● Log file name specified once
  • 20.
    Magento Best Practices- 20/53 Meet Magento IT – March 5th-6th, 2015 Logging: custom Custom log wrapper https://github.com/aleron75/magelog Monolog wrapper https://github.com/aleron75/magemonolog
  • 21.
    Magento Best Practices- 21/53 Meet Magento IT – March 5th-6th, 2015 Autoloading Magento’s autoloader is registered at the very beginning of framework's bootstrap: it is difficult (not impossible) to extend It's not natively PSR−0 compliant (PHP-FIG's birth follows Magento's)
  • 22.
    Magento Best Practices- 22/53 Meet Magento IT – March 5th-6th, 2015 The Magento-PSR-0-Autoloader extension registers an additional autoloader which gives the ability to include libraries adhering to PSR−0 Autoloading Standard (i.e.: Monolog) Autoloading: enable PSR-0
  • 23.
    Magento Best Practices- 23/53 Meet Magento IT – March 5th-6th, 2015 Effective MVC MVC is a good example of separation of concerns principle That doesn't mean we don't have to pay attention to avoid messing up things anyway
  • 24.
    Magento Best Practices- 24/53 Meet Magento IT – March 5th-6th, 2015 Effective MVC: Models A Model is the entity which describes the problem we want to solve in terms of states and business logic
  • 25.
    Magento Best Practices- 25/53 Meet Magento IT – March 5th-6th, 2015 Effective MVC: Models ● Keep Models simple and focused on a single concern ● Choose the least visibility scope for methods and declare classes final ● Prefer composition over inheritance (as far as possible)
  • 26.
    Magento Best Practices- 26/53 Meet Magento IT – March 5th-6th, 2015 Effective MVC: Models Benefits of keeping Models simple: ● fewer reasons to change ● easier to upgrade ● easier to test ● clean interface ● smaller method signatures
  • 27.
    Magento Best Practices- 27/53 Meet Magento IT – March 5th-6th, 2015 Effective MVC: Blocks & Templates Blocks are responsible for presentation data logic Templates are responsible for presentation logic
  • 28.
    Magento Best Practices- 28/53 Meet Magento IT – March 5th-6th, 2015 Effective MVC: Blocks & Templates Prefer single points of definition: ● No direct data/config access in Blocks; use Models and Helpers instead ● Delegate to children Blocks whenever possible (i.e.: Mage_Catalog_Block_Product_Price) ● Templates should only interact with their Blocks ● Enable cache on custom Blocks
  • 29.
    Magento Best Practices- 29/53 Meet Magento IT – March 5th-6th, 2015 Effective MVC: Controllers “a Controller accepts input and converts it to commands for the Model or View” - Wikipedia Controllers manage application flow
  • 30.
    Magento Best Practices- 30/53 Meet Magento IT – March 5th-6th, 2015 Effective MVC: Controllers ● Check user input is well-formed i.e.: 16 digits required for a MasterCard number ● Don't perform business domain checks i.e.: whether a MasterCard number is authorized
  • 31.
    Magento Best Practices- 31/53 Meet Magento IT – March 5th-6th, 2015 Effective MVC: Helpers They are not waste baskets :) ● utility methods containers (Core Helpers represent a very good example) ● shouldn't implement logic. For complex logic use service Models @see Mage_Sales_Model_Service_Quote
  • 32.
    Magento Best Practices- 32/53 Meet Magento IT – March 5th-6th, 2015 Working with Data Adopting best practices can avoid unexpected performance downgrade or behaviour. Simply put: write scalable code
  • 33.
    Magento Best Practices- 33/53 Meet Magento IT – March 5th-6th, 2015 Working with Data: EAV and Flat ● Flat is never used for EAV entities in Admin Panel ● load() method always performs joins on EAV tables ● Flat for EAV entities is only used for Collections (unless filtering on non- flat attributes)
  • 34.
    Magento Best Practices- 34/53 Meet Magento IT – March 5th-6th, 2015 Working with Data: Products Don't try this at home: $products = Mage::getModel('catalog/product')   ­>getCollection(); foreach ($products as $prod) {   $prod­>load($prod­>getId()); # doesn't scale!   echo $prod­>getDescription(); }
  • 35.
    Magento Best Practices- 35/53 Meet Magento IT – March 5th-6th, 2015 Working with Data: Products The following code is better for scalability: $products = Mage::getModel('catalog/product')   ­>getCollection()   ­>addAttributeToSelect(array('description')); foreach ($products as $prod) {   echo $prod­>getDescription(); }
  • 36.
    Magento Best Practices- 36/53 Meet Magento IT – March 5th-6th, 2015 Working with Data: Products Comparison table*: Load type # queries # joins Time Memory In loop 875 1072 ~4 sec ~7 MB Outside loop 8 1 ~0.4 sec ~2.5 MB * on a development machine with official sample data
  • 37.
    Magento Best Practices- 37/53 Meet Magento IT – March 5th-6th, 2015 Working with Data: Collection size Comparison table*: Count type Time Memory count() ~0.966 sec ~25 MB getSize() ~0.081 sec ~1.8 MB * on a development machine with ~8000 products
  • 38.
    Magento Best Practices- 38/53 Meet Magento IT – March 5th-6th, 2015 Working with Data: iterate Collection Iterating: non-scalable approach $products = Mage::getModel('catalog/product')   ­>getCollection(); /** @var Mage_Catalog_Model_Product $product */ foreach ($products as $product) {   // do something ­ lazy loading is triggered }
  • 39.
    Magento Best Practices- 39/53 Meet Magento IT – March 5th-6th, 2015 Working with Data: iterate Collection Iterating: scalable approach $products = Mage::getModel('catalog/product')   ­>getCollection(); /** @var array $productData */ foreach ($products­>getData() as $productData) {   // do something }
  • 40.
    Magento Best Practices- 40/53 Meet Magento IT – March 5th-6th, 2015 Working with Data: iterate Collection Iterating: alternative scalable approach $products = Mage::getModel('catalog/product')   ­>getCollection(); /** @var Varien_Object $object */ while ($object = $products­>fetchItem()) {   // do something }
  • 41.
    Magento Best Practices- 41/53 Meet Magento IT – March 5th-6th, 2015 Working with Data: iterate Collection Comparison table*: Fetch collection items Time Memory standard ~1.913 sec ~25 MB getData() ~0.017 sec ~1.3 MB fetchItem() ~0.026 sec ~1.1 MB * on a development machine with official sample data
  • 42.
    Magento Best Practices- 42/53 Meet Magento IT – March 5th-6th, 2015 Working with Data: save attribute value The following code takes ~1.5 seconds to be executed on a development machine: $product = Mage::getModel('catalog/product')   ­>load(<existing_product_id>); $product   ­>setDataChanges(true) // force save   ­>save();
  • 43.
    Magento Best Practices- 43/53 Meet Magento IT – March 5th-6th, 2015 Working with Data: save attribute value To save only some values a better approach is:   $product = Mage::getModel('catalog/product')   ­>load(<existing_product_id>)   ­>setName('New name')   ­>setDescription('New description')   ­>getResource()   ­>saveAttribute($product, 'name')   ­>saveAttribute($product, 'description');
  • 44.
    Magento Best Practices- 44/53 Meet Magento IT – March 5th-6th, 2015 Working with Data: save attribute value Comparison table*: Save method Time Memory save() ~1.5 sec ~5 MB saveAttribute() ~0.02 sec a few KB * on a development machine with official sample data
  • 45.
    Magento Best Practices- 45/53 Meet Magento IT – March 5th-6th, 2015 Extending Magento Never touch the core files!
  • 46.
    Magento Best Practices- 46/53 Meet Magento IT – March 5th-6th, 2015 Extending Magento: monkey patch Monkey patches are a (non upgrade safe) way to change a core class without touching the original file by copying it from the core code pool to the local one. Possible use cases: ● patching the core ● rapid prototyping
  • 47.
    Magento Best Practices- 47/53 Meet Magento IT – March 5th-6th, 2015 Extending Magento: rewrites Rewrites are the first step towards extending Magento according to best practices. Pros ● upgrade safe Cons ● only one rewrite of same class → potential conflicts ● not compliant with the open/closed principle
  • 48.
    Magento Best Practices- 48/53 Meet Magento IT – March 5th-6th, 2015 Extending Magento: events Events represent the standard best way to extend other classes behaviour. Pros ● upgrade safe ● no conflicts: multiple observers on same event Cons ● no event → no observer
  • 49.
    Magento Best Practices- 49/53 Meet Magento IT – March 5th-6th, 2015 Extending Magento: interceptors Interceptors are a way to change the behavior of any public or protected method, by either executing code before or after that method. They are native on Magento 2 but can be also added to Magento 1 thanks to: https://github.com/danslo/Danslo_Aop
  • 50.
    Magento Best Practices- 50/53 Meet Magento IT – March 5th-6th, 2015 Extending Magento: interceptors Pros ● Upgrade safe ● No conflicts ● Any public/protected method can be intercepted, no need of events Cons ● Logic can be injected only at the beginning or at the end, not in the middle of a method
  • 51.
    Magento Best Practices- 51/53 Meet Magento IT – March 5th-6th, 2015 Conclusions ● Use the best available tools ● Use runtime outside Magento modules ● Don't use Mage::log() ● Extending autoloading is possible and useful ● Write effective and solid MVC components ● Data: write scalable code ● Never touch the core, prefer events to rewrites, familiarize with interceptors
  • 52.
    Magento Best Practices- 52/53 Meet Magento IT – March 5th-6th, 2015 The Handbook https://leanpub.com/magebp ● If you liked this talk you'll love the e-book :) ● Special 25% discount code for you: mm15it ● Release date: ~June 2015
  • 53.
    Magento Best Practices- 53/53 Meet Magento IT – March 5th-6th, 2015 Thank you! QUESTIONS? https://twitter.com/aleron75 https://github.com/aleron75