Top Banner
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 -
53
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Magento best practices

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 -

Page 2: Magento best practices

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”

Page 3: Magento best practices

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

Page 4: Magento best practices

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

Page 5: Magento best practices

Magento Best Practices - 5/53 Meet Magento IT – March 5th-6th, 2015

About you

● Developers?● Programmers?● Coders?● What else?

Page 6: Magento best practices

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

Page 7: Magento best practices

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

Page 8: Magento best practices

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

Page 9: Magento best practices

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

Page 10: Magento best practices

Magento Best Practices - 10/53 Meet Magento IT – March 5th-6th, 2015

Magento RuntimeWhy● to check code inside a full initialized

Magento application

How● Write a Module (slow)● Write a Shell Script (faster)● Use bash snippet (fastest)

Page 11: Magento best practices

Magento Best Practices - 11/53 Meet Magento IT – March 5th-6th, 2015

Magento Runtime: Shell Script● Extend Mage_Shell_Abstract● Set proper store scopeprotected $_appCode = 'admin';

● Override _applyPhpVariables()● Load app area in _construct()

– Mage_Core_Model_App_Area::AREA_FRONTEND

– Mage_Core_Model_App_Area::AREA_ADMINHTML

Page 12: Magento best practices

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

Page 13: Magento best practices

Magento Best Practices - 13/53 Meet Magento IT – March 5th-6th, 2015

Magento Runtime: ready snippets

Customerhttps://gist.github.com/aleron75/190b25ea621c14a21d6b

Administratorhttps://gist.github.com/aleron75/9d6609e99153d19461f3

Page 14: Magento best practices

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

Page 15: Magento best practices

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");

Page 16: Magento best practices

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

Page 17: Magento best practices

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'));

Page 18: Magento best practices

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

Page 19: Magento best practices

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

Page 20: Magento best practices

Magento Best Practices - 20/53 Meet Magento IT – March 5th-6th, 2015

Logging: custom

Custom log wrapperhttps://github.com/aleron75/magelog

Monolog wrapperhttps://github.com/aleron75/magemonolog

Page 21: Magento best practices

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)

Page 22: Magento best practices

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

Page 23: Magento best practices

Magento Best Practices - 23/53 Meet Magento IT – March 5th-6th, 2015

Effective MVC

MVC is a good exampleof separation of concerns principle

That doesn't mean we don't have to pay attention to avoid messing up

things anyway

Page 24: Magento best practices

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

Page 25: Magento best practices

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)

Page 26: Magento best practices

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

Page 27: Magento best practices

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

Page 28: Magento best practices

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

Page 29: Magento best practices

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

Page 30: Magento best practices

Magento Best Practices - 30/53 Meet Magento IT – March 5th-6th, 2015

Effective MVC: Controllers

● Check user input is well-formedi.e.: 16 digits required for a MasterCard number

● Don't perform business domain checksi.e.: whether a MasterCard number is authorized

Page 31: Magento best practices

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

Page 32: Magento best practices

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

Page 33: Magento best practices

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)

Page 34: Magento best practices

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

}

Page 35: Magento best practices

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

}

Page 36: Magento best practices

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

Page 37: Magento best practices

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

Page 38: Magento best practices

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

}

Page 39: Magento best practices

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

}

Page 40: Magento best practices

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

}

Page 41: Magento best practices

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

Page 42: Magento best practices

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

Page 43: Magento best practices

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');

Page 44: Magento best practices

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

Page 45: Magento best practices

Magento Best Practices - 45/53 Meet Magento IT – March 5th-6th, 2015

Extending Magento

Never touch the core files!

Page 46: Magento best practices

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

Page 47: Magento best practices

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

Page 48: Magento best practices

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

Page 49: Magento best practices

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

Page 50: Magento best practices

Magento Best Practices - 50/53 Meet Magento IT – March 5th-6th, 2015

Extending Magento: interceptorsPros● 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

Page 51: Magento best practices

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

Page 52: Magento best practices

Magento Best Practices - 52/53 Meet Magento IT – March 5th-6th, 2015

The Handbookhttps://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

Page 53: Magento best practices

Magento Best Practices - 53/53 Meet Magento IT – March 5th-6th, 2015

Thank you!

QUESTIONS?

https://twitter.com/aleron75

https://github.com/aleron75