Code Generation in Magento 2

Preview:

Citation preview

Code Generationin Magento 2

Sergii ShymkoSenior Software EngineerMagento, an eBay Inc. company

Legal Disclaimer

Copyright © 2015 Magento, Inc. All Rights Reserved.

Magento®, eBay Enterprise™ and their respective logos are trademarks, service marks, registered trademarks, or registered service marks of eBay, Inc. or its subsidiaries. Other trademarks or service marks contained in this presentation are the property of the respective companies with which they are associated.

This presentation is for informational and discussion purposes only and should not be construed as a commitment of Magento, Inc. or eBay Enterprise (“eBay Enterprise”) or of any of their subsidiaries or affiliates. While we attempt to ensure the accuracy, completeness and adequacy of this presentation, neither Magento, Inc., eBay Enterprise nor any of their subsidiaries or affiliates are responsible for any errors or will be liable for the use of, or reliance upon, this presentation or any of the information contained in it. Unauthorized use, disclosure or dissemination of this information is expressly prohibited.

Introduction to Code Generation

• Automatic programming – generation of computer program• Source code generation

– Generation based on template• Allows to write code at higher abstraction level• Enables aspect-oriented programming (AOP)• Enables generic programming – parameterization over types• Avoids writing boilerplate code

Code Generation in Magento 1.x

Code Generation in Magento 2

Code Generation in Magento 2

• Code is generated:– On the fly (development)

• Autoload non-existing class that follows naming pattern– Beforehand (production)

• Run CLI toolsphp dev/tools/Magento/Tools/Di/compiler.php

• Location of generated code:var/generation/

Factories

• Factory creates objects• Single method – create()• Used for non-injectables, i.e. entities• Isolation from Object Manager• Type safety• IDE auto-completion• Class name pattern:

\Namespace\ClassFactory

Factory Usage

namespace Magento\Catalog\Model\Product;

class Copier{ public function __construct( \Magento\Catalog\Model\ProductFactory $productFactory ) { $this->productFactory = $productFactory; }

public function copy(\Magento\Catalog\Model\Product $product) { $duplicate = $this->productFactory->create(); // ... }}

app/code/Magento/Catalog/Model/Product/Copier.php

Generated Factory (Simplified)

namespace Magento\Catalog\Model;

class ProductFactory{ public function __construct( \Magento\Framework\ObjectManagerInterface $objectManager ) { $this->objectManager = $objectManager; }

public function create(array $data = array()) { return $this->objectManager->create( '\\Magento\\Catalog\\Model\\Product', $data ); }}

var/generation/Magento/Catalog/Model/ProductFactory.php

Proxies

• Implementation of GoF pattern• Follows interface of subject• Delays creation of subject

– Delays creation of dependencies• Forwards calls to subject• Used for optional dependencies of DI• Class name pattern:

\Namespace\Class\Proxy

Proxy Usage in DI Config

<config> <type name="Magento\Catalog\Model\Resource\Product\Collection"> <arguments> <argument name="customerSession" xsi:type="object"> Magento\Customer\Model\Session\Proxy </argument> </arguments> </type></config>

app/code/Magento/Catalog/etc/di.xml

Generated Proxy (Simplified)

namespace Magento\Customer\Model\Session;

class Proxy extends \Magento\Customer\Model\Session{ protected function getSubject() { if (!$this->subject) { $this->subject = $this->objectManager->get( '\\Magento\\Customer\\Model\\Session' ); } return $this->subject; }

public function getCustomerId() { return $this->getSubject()->getCustomerId(); }

// ...}

var/generation/Magento/Customer/Model/Session/Proxy.php

Interception

• Primary customization approach• AOP-like mechanism• Used for plugins• Attach behavior to public methods

– Before– After– Around

• Plugins declared in DI config

Plugin Implementation

namespace Magento\Store\App\Action\Plugin;

class StoreCheck{ public function aroundDispatch( \Magento\Framework\App\Action\Action $subject, \Closure $proceed, \Magento\Framework\App\RequestInterface $request ) { if (!$this->storeManager->getStore()->getIsActive()) { throw new \Magento\Framework\App\InitException( 'Current store is not active.' ); } return $proceed($request); }}

app/code/Magento/Store/App/Action/Plugin/StoreCheck.php

Plugin Declaration in DI Config

<config> <type name="Magento\Framework\App\Action\Action"> <plugin name="storeCheck" type="Magento\Store\App\Action\Plugin\StoreCheck" sortOrder="10"/> </type></config>

app/code/Magento/Store/etc/di.xml

Generated Interceptor (Simplified)

namespace Magento\Framework\App\Action\Action;

class Interceptor extends \Magento\Framework\App\Action\Action{ public function dispatch( \Magento\Framework\App\RequestInterface $request ) { $pluginInfo = $this->pluginList->getNext( '\\Magento\\Framework\\App\\Action\\Action', 'dispatch' ); if (!$pluginInfo) { return parent::dispatch($request); } else { return $this->___callPlugins( 'dispatch', func_get_args(), $pluginInfo ); } }}

var/generation/Magento/Framework/App/Action/Action/Interceptor.php

Code Generation for Service Layer

• Service layer – ultimate public API• Services implement stateless operations• Generated code:

– Repository*– Persistor*– Search Results– Extension Attributes

* – may be removed in future releases

Generated Repository (Simplified)

namespace Magento\Sales\Api\Data\Order;

class Repository implements \Magento\Sales\Api\OrderRepositoryInterface{ public function __construct( \Magento\Sales\Api\Data\OrderInterfacePersistor $orderPersistor, \Magento\Sales\Api\Data\OrderSearchResultInterfaceFactory $searchResultFactory ) { $this->orderPersistor = $orderPersistor; $this->searchResultFactory = $searchResultFactory; }

public function get($id); public function create(\Magento\Sales\Api\Data\OrderInterface $entity); public function getList(\Magento\Framework\Api\SearchCriteria $criteria); public function remove(\Magento\Sales\Api\Data\OrderInterface $entity); public function flush();}

var/generation/Magento/Sales/Api/Data/Order/Repository.php

Extension Attributes

• Extension to data interfaces from 3rd party modules• Attributes declared in configuration• Attribute getters/setters generated• Type-safe attribute access• IDE auto-completion• Class name pattern:

\Namespace\ClassExtensionInterface\Namespace\ClassExtension

Declaration of Extension Attributes

<config> <custom_attributes for="Magento\Catalog\Api\Data\ProductInterface"> <attribute code="price_type" type="integer" /> </custom_attributes></config>

app/code/Magento/Bundle/etc/data_object.xml

Entity with Extension Attributes

namespace Magento\Catalog\Api\Data;

interface ProductInterface extends \Magento\Framework\Api\CustomAttributesDataInterface{ /** * @return \Magento\Catalog\Api\Data\ProductExtensionInterface|null */ public function getExtensionAttributes();

public function setExtensionAttributes( \Magento\Catalog\Api\Data\ProductExtensionInterface $attributes );

// ...}

app/code/Magento/Catalog/Api/Data/ProductInterface.php

Generated Interface of Extension Attributes

namespace Magento\Catalog\Api\Data;

interface ProductExtensionInterface extends \Magento\Framework\Api\ExtensionAttributesInterface{ /** * @return integer */ public function getPriceType();

/** * @param integer $priceType * @return $this */ public function setPriceType($priceType);

// ...}

var/generation/Magento/Catalog/Api/Data/ProductExtensionInterface.php

Generated Implementation of Extension Attributes

namespace Magento\Catalog\Api\Data;

class ProductExtension extends \Magento\Framework\Api\AbstractSimpleObject implements \Magento\Catalog\Api\Data\ProductExtensionInterface{ /** * @return integer */ public function getPriceType() { return $this->_get('price_type'); } /** * @param integer $priceType * @return $this */ public function setPriceType($priceType) { return $this->setData('price_type', $priceType); }

// ...}

var/generation/Magento/Catalog/Api/Data/ProductExtension.php

Loggers

• Implementation of GoF pattern Decorator• Activated with the profiler

– Object Manager wraps instances with loggers• Tracks method call stack• Forwards calls to original methods• Class name pattern:

\Namespace\Class\Logger

Summary of Code Generation

• DI– Factory– Proxy

• Interception• Service Layer

– Repository– Persistor– Search Results– Extension Attributes

• Logger

Thank You!Q & ASergii Shymko

sshymko@ebay.com

Resources

• github.com– magento/magento2 – Magento 2 Community Edition– magento/magento2-community-edition – Composer project for

Magento 2 CE• devdocs.magento.com

– Factories– Proxies– Plugins– Definition compilation tool

Recommended