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