meet magento sweden - magento 2 layout and code compilation for performance
TRANSCRIPT
REPEATED DATA PROCESSING// ... some xml/json/yaml file initialization foreach ($loadedData as $item) { $this->process($item); }
NESTED LOOPSforeach ($data as $item) { $row = []; foreach ($columns as $column) { $row[] = $column->export($item); } $csv->write($row); }
COMPLEX DEPENDENCY TREEclass ClassOne { public function __construct(ClassTwo $dependency) {} }
class ClassTwo { public function __construct(ClassThree $dependency) {} }
class ClassThree { public function __construct(ClassFour $dependencyOne, ClassFive $dependencyTwo}
// ..
REPEATED DATA PROCESSINGTranslate your XML/JSON/YAML file into executable PHPcode and include it when you need processed structure
BUT COMPILATION LOOKS UGLY...You need to create PHP code within PHP codeYou need to write it to external fileYou need to include that file inside of your code
ECOMDEV\COMPILERCreated to wrap writing PHP code within PHPAutomatically stores compiled codeAutomatically validates source and re-compiles codewhen neededProvides easy to use API to create parsers, builders andexecutors
INSTALLATION1. Available as a composer dependency
2. Instantiate it directly or via DI container.
composer require "ecomdev/compiler"
XML FILE<objects> <item id="object_one" type="object" /> <item id="object_two" type="object" /> <item id="object_three" type="object" /> <type id="object" class="Some\ClassName"/> </objects>
PARSERuse 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 DATAprivate 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 CODEprivate function getPhpCode($info, $builder) { $compiledArray = [];
foreach ($info['objects'] as $objectId => $type) { $compiledArray[$objectId] = $builder->instance($info['types'][ }
return $builder->container( $builder->returnValue($compiledArray) ); }
COMPILED PHP FILEreturn [ 'object_one' => new Some\ClassName(), 'object_two' => new Some\ClassName(), 'object_three' => new Some\ClassName() ];
YOUR CONSTRUCTORpublic function __construct( EcomDev\Compiler\Builder $builder, EcomDev\Compiler\Compiler $compiler) { $this->builder = $builder; $this->compiler = $compiler; }
EXPORT METHODpublic 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 METHODpublic function compileColumns($columns, $builder) { $item = $builder->variable('item');
$compiledArray = []; foreach ($columns as $id => $column) { $compiledArray[] = $builder->chainVariable('columns')[$id] ->export($item); }
$closure = $builder->closure( [$item, $builder->variable('columns')], $builder->container([$builder->returnValue($compiledArray)]) );
return $builder->container([$builder->returnValue($closure)]); }
RESULTreturn function ($item, $columns) { return [ $columns['id1']->export($item), $columns['id2']->export($item), $columns['id3']->export($item), // ... ]; };
MAIN COMPONENTSCompilerInterface - Compiler instanceStorageInterface - Stores compiled filesSourceInterface - Provider of data (File, String,StaticData)ParserInterface - Parser of dataObjectBuilderInterface - Bound builder for included files
EXPORTABLE OBJECTSclass 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');
LAYOUT CACHINGEvery handle that is added to the
Magento\Framework\View\Result changes the cache keyfor the whole generated structure.
GITHUBCOMPILER LIBRARY FOR M2
https://github.com/EcomDev/compiler
LAYOUT COMPILER FOR M1
https://github.com/EcomDev/EcomDev_LayoutCompiler
LAYOUT COMPILER FOR M2
Coming soon