Magento 2

Layout and Code Compilation for Performance


by Ivan Chepurnyi

What? Compilation?

Complex Simple algorithms

What makes them complex?

Repeated data processing

// ... some xml/json/yaml file initialization
foreach ($loadedData as $item) {

Nested loops

foreach ($data as $item) {
    $row = [];
    foreach ($columns as $column) {
       $row[] = $column->export($item);

Complex dependency tree

class ClassOne
     public function __construct(ClassTwo $dependency) {}

class ClassTwo
    public function __construct(ClassThree $dependency) {}

class ClassThree
    public function __construct(ClassFour $dependencyOne, ClassFive $dependencyTwo) {}

// ..

How can we solve it?

Repeated data processing

Translate your XML/JSON/YAML file into executable PHP code and include it when you need processed structure

Nested loops

Pre-compile second loop and execute it within the main one

Complex dependency tree

Resolve dependencies and compile resolution into executable code

But compilation looks ugly...

  • You need to create PHP code within PHP code
  • You need to write it to external file
  • You need to include that file inside of your code

I was looking for a library

Didn't find one... So I wrote it myself.


  • Created to wrap writing PHP code within PHP
  • Automatically stores compiled code
  • Automatically validates source and re-compiles code when needed
  • Provides easy to use API to create parsers, builders and executors


  1. Available as a composer dependency
    composer require "ecomdev/compiler"
  2. Instantiate it directly or via DI container.

Some examples

Compile XML into PHP

XML file

    <item id="object_one" type="object" />
    <item id="object_two" type="object" />
    <item id="object_three" type="object" />
    <type id="object" class="Some\ClassName"/>


use EcomDev\Compiler\Statement\Builder;

class Parser implements EcomDev\Compiler\ParserInterface
    // .. constructor with builder as dependency
    public function parse($value)
        $xml = simplexml_load_string($value);
        $info = $this->readXml($xml);
        return $this->getPhpCode($info, $this->builder);
    // .. other methods

Parse xml data

private function readXml($xml)
    $info = [];
    foreach ($xml->children() as $node) {
        if ($node->getName() === 'type') {
            $info['types'][(string)$node->id] = (string)$node->class;
        } elseif ($node->getName() === 'object') {
            $info['objects'][(string)$node->id] = (string)$node->type;

    return $info;

Create PHP code

private function getPhpCode($info, $builder) {
    $compiledArray = [];

    foreach ($info['objects'] as $objectId => $type) {
        $compiledArray[$objectId] = $builder->instance($info['types'][$type]);

    return $builder->container(

Compiled PHP File

return [
    'object_one' => new Some\ClassName(),
    'object_two' => new Some\ClassName(),
    'object_three' => new Some\ClassName()

Nested Loop Simplifying

Your constructor

public function __construct(
    EcomDev\Compiler\Builder $builder,
    EcomDev\Compiler\Compiler $compiler)
    $this->builder = $builder;
    $this->compiler = $compiler;

Export method

public function export($data, $columns)
    $statements = $this->compileColumns($columns, $this->builder);

    $source = new \EcomDev\Compiler\Source\StaticData(
        'your_id', 'your_checksum', $statements

    $reference = $this->compiler->compile($source);
    $closure = $this->compiler->interpret($reference);

    foreach ($data as $item) {
       $row = $closure($item, $columns);

Compilation method

public function compileColumns($columns, $builder)
    $item = $builder->variable('item');

    $compiledArray = [];
    foreach ($columns as $id => $column) {
        $compiledArray[] = $builder->chainVariable('columns')[$id]

    $closure = $builder->closure(
        [$item, $builder->variable('columns')],

    return $builder->container([$builder->returnValue($closure)]);


return function ($item, $columns) {
    return [
        // ...

Main Components

  • CompilerInterface - Compiler instance
  • StorageInterface - Stores compiled files
  • SourceInterface - Provider of data (File, String, StaticData)
  • ParserInterface - Parser of data
  • ObjectBuilderInterface - Bound builder for included files

And some sweet stuff...

Exportable Objects

class SomeClass implements EcomDev\Compiler\ExportableInterface
    public function __construct($foo, $bar) { /* */ }

    public function export() {
        return [
            'foo' => $this->foo,
            'bar' => $this->bar

Will be automatically compiled into:

new SomeClass('fooValue', 'barValue');

Magento 2.0

Layout Compilation is a must

Why? Because of its algorithm

Layout caching

Every handle that is added to the Magento\Framework\View\Result changes the cache key for the whole generated structure.

Layout generation

Scheduled structure is generated from XML object at all times


1. Make every handle a compiled php code

2. Include compiled handles at loading phase

Good news

I am already working on it

Will be release in April 2016


Compiler Library for M2

Layout Compiler for M1

Layout Compiler for M2

Coming soon

Thank You