Applying Code Customizations to Magento 2

Post on 08-Jan-2017

64 views 1 download

transcript

Applying Code Customizations to

Magento 2

Who am I?

Igor Miniailo

Interactions with Magento2 Code

Extension

UI Model

UI

ModelService

Contracts

Service Contracts

Vendor

Customization

UI Model

Model

Service Contracts

Vendor

Customization Points

Customization points

Admin Configuration

Low Level Linking

High-level configuration (DSLs)events.xml

routes.xml

routes.xml webapi.xml

acl.xml

di.xml

Object B Object C Object A

Object B

config.xml

Store Configuration

Store Configuration

• In admin application: Stores->Configuration• Values stored in Database• Configured in system.xml• Default values in config.xml

High Level Configuration

Routing

High-level Configuration

Event Manager

events.xml

routes.xml

Application subsystems

AreaApplication

EntryPoint

Cron App

Web App

WebAPI

Admin

FrontendMedia App

Low Level linking

1. Composability2. Modularity

Composability

Composability

Split your code to lots of small chunks and then compose them to

build your application

Dependency InjectionDependencies are not located within object but are provided to that object by environment

namespace Magento\Framework\Event;class Manager implements ManagerInterface{

public function __construct(Invoker $invoker,Config $eventConfig,$prefix = '') {$this->_invoker = $invoker;$this->_eventConfig = $eventConfig;$this->_prefix = $prefix;}// some other code

}

Unit Tests

class ManagerTest extends \PHPUnit_Framework_TestCase{ protected function setUp() { $this->_invoker = $this->getMock('Magento\Framework\Event\Invoker'); $this->_eventConfigMock = $this->getMock('Magento\Framework\Event\Config'); $this->_eventManager = new \Magento\Framework\Event\Manager(

$this->_invoker,$this->_eventConfigMock

); }}

SOLID

1. Single responsibility – Lots of small objects

2. Open Closed - Each object has multiple extension points

3. Liskov Substitution – Polymorphism for composability

4. Interface Segregation – Granularity

5. Dependency Inversion – Decoupling. In particular, any caller of an interface depends only on the interface, even if a separate module implements it.

Modularity

SOLId

Module BModule A

Implementation

Module B

Module A Implementation

Interface

Module C

Implementation

Module AB

Module AC

Impl

Impl

Coupled

Decoupled

Modules Definition

Modules serve as named containers for domain object classes that are highly cohesive with one another.The goal should be low coupling between the classes that are in different Modules

Simple rules for Module design

• Ensuring that Modules are largely independent of others has the same benefit as loosely coupled classes. This will make it easier to maintain and refactor code inside the module.

• Do strive for acyclic dependencies on Modules where coupling is necessary. Just unidirection

Service Contracts

And Compatible Customizations

Extensions Compatibility Challenges

Interfaces may be changed in a new version Extensions may depend on optional modules which is turned off Extensions may depend on undocumented behavior

How to ensure that two extensions will be compatible in a new version?

Challenges for Developer

How to understand what functionality of the extension is stable and what is not?

How to implement extension in the way that it will keep backward compatibility but can evolve?

Stable APIs

Backward Compatible: Classes or Interfaces are not removed Methods of the classes keeps signature between versions Interfaces neither changes existing methods nor add new ones

Explicit Interfaces No generic data types as “mixed”, “object” or “array”

Few ways to make promises in Magento 2

Semantic Versioning of the modules makes dependencies between modules explicit

{ "name": "magento/module-catalog-inventory", "require": { "magento/module-customer": "0.74.0-beta2" }, "type": "magento2-module"}

/** * @api */interface AuthorizationInterface{ /** * Check current user permission on resource and privilege * * @param string $resource * @param string $privilege * @return boolean */ public function isAllowed($resource, $privilege = null);}

@api annotation identifies subset of the methods with the stable APIs

Enforced by tools and static tests

Magento 1.x Domain Level API

Model is an entry point to the Module Interface implicitly defined via the

database schema No single place for the business rules

They can be in: Controllers Models Helpers Templates

Model

Resource Model

ClientgetData()

Repositories

Service Contracts

Models

Resource Models/Entity

Manager

Web API clients

M2 Module

Blocks TemplatesControllers

Other M2 Modules

Services

Data Objects

Service Contracts

Domain Level API

Single way to define API for the business feature Defines strong interface Single place to implement business rules All interactions with the module are safe to

go through the contracts: same behavior guaranteed

Repositories

Service Contracts

Models

Resource Models/Entity

Manager

M2 Module

Blocks TemplatesControllers

Services

Data Objects

Service Contracts Interfaces

Service Contracts

Service Interfaces Data Interface

Data interfaces Defines data structures, used as input and

output types of the business operations Examples: Customer, Product, Region,

Currency, etc.

Service interfaces Defines business operations Examples: load, delete, save, change

password, etc.

They are just PHP Interfaces

More on Data Interfaces

Has just setters and getters to describe a data

Reusable across different Service interfaces

Encapsulates all the data needed to process service request

Can be Serialized Annotations are used to extract the data

More on Service Interfaces

Defines public operations supported by the module

Methods are independent and stateless. Invocation of one method should not

affect the result of another

Methods combined in interface by cohesion principle

Annotated with types information

Classes Implementing Data Interfaces

It can be Model (NOT Recommended): All the setters and getters should be

declared explicitly No magic methods

It can be Any PHP class: Implements data interface and any

other methods It can be Data Object:

Implements just methods from the data interface

Models

Data Objects

Data Interfaces

Implementation of Service Interfaces

Resource Models (legacy, not recommended): Used for persistence operations Implements load/save/delete

methods and accept Data Interface as an input

Entity Manager: Used for persistence operations ORM implementation

Services: Implements operations and business

rules around them

Service Interfaces

Resource Models/EntityM

anagerServices

Use Service Contracts

Define dependency on service interface in the constructorclass CreateCustomer extends \Magento\Customer\Controller\Account{ public function __construct( AccountManagementInterface $accountManagement ) { $this->accountManagement = $accountManagement; }

public function execute() { $customer = $this->getRequest()->getParam('customer'); $password = $this->getRequest()->getParam('password'); $redirectUrl = $this->getRequest()->getParam('redirect_url'); $customer = $this->accountManagement ->createAccount($customer, $password, $redirectUrl); … }}

Re-Implement Service Contracts

Define a preference in DI: it will point on a new implementation All the constructors will be injected with a new implementation

<preference for="Magento\Customer\Api\AccountManagementInterface" type="SomeVendor\NewExtension\Model\AccountManagement" />

<preference for="Magento\Customer\Api\Data\RegionInterface" type="SomeVendor\NewExtension\Model\Data\Region" />

Customize Service Contracts

Plugins is a way to add new behavior each time Service Interface implementation is invoked

/** * Plugin after create customer that updates any newsletter subscription that may have existed. * * @param CustomerRepositoryInterface $subject * @param CustomerInterface $customer * @return CustomerInterface */public function afterSave(CustomerRepositoryInterface $subject, CustomerInterface $customer){ $this->subscriberFactory->create()->updateSubscription($customer->getId()); return $customer;}

Extend Data Interfaces

Extension Attributes is a way to Extend Data Interfaces from third-party module

Added via xml configuration, generated as an object

Review fields

Catalog Inventory fields

Rating and Reviews Module Catalog

Inventory Module

Product Data Interface

Product fields

Generated Extension Attributes

<extension_attributes for="Magento\Catalog\Api\Data\ProductInterface"> <attribute code="bundle_product_options" type="Magento\Bundle\Api\Data\OptionInterface[]" /></extension_attributes>

interface ProductExtensionInterface extends \Magento\Framework\Api\ExtensionAttributesInterface{ /** * @return \Magento\Bundle\Api\Data\OptionInterface[] */ public function getBundleProductOptions();

/** * @param \Magento\Bundle\Api\Data\OptionInterface[] $bundleProductOptions * @return $this */ public function setBundleProductOptions($bundleProductOptions);...}

Summary

Magento 2.x gives stronger promises on public APIs

Service Contracts are the way to define API for the Business features Service Contracts should be the single entry point to functionality of the

module Customizable via dependency injection, plugins and extension attributes

Customizations become available for all the clients of Service Contracts

Thank you!

Igor Miniailoiminiailo@magento.com

Q & A