A deep dive into Magento 2's core functionality specifically around service contracts, repositories and data persistence. This also discusses the future of Magento 2's architecture.
1. Magento 2
The State of Data Persistence
(Being Pragmatic in the Face of Architectural Uncertainty)
@matthewhaworth
2. A quick about me
Matthew Haworth
Magento Consultant at Warner Music Group
Twitter: @matthewhaworth
LinkedIn: matthewhaworth
@matthewhaworth
3. My first experience with Magento 2.0
• Stayed in my comfort zone using old ‘Active Record’ façade
$product = $productFactory->create()->load($productId);
$product->setName(‘New Product Name');
$product->save();
• Learned about new ‘Service Contracts’ architecture, but avoided it
• Eventually dug deeper, learned more best practice and want to
evangelise
@matthewhaworth
4. Magento 1 Architecture Review
• The Active Record pattern implied that a Model was responsible for
persisting data to the database through ->save()
• However, the Model delegated to the Resource Model
• The Resource Model iterated through the database table’s fields and
pulled those keys from the Model to create an insert/update query.
@matthewhaworth
Model
Resource
Model
->save() ->save($this)
5. Magento 1 Architecture Review
• The Model was responsible for modelling the data.
• The Resource Model was effectively a Data Mapper.
• Any business logic was either in the Model or in a custom
built service class
@matthewhaworth
6. Magento 2’s New Architecture
• Magento 2 seeks to formalise this structure by introducing ‘Service
Contracts’.
• Service contracts are a set of interfaces defined for data models and
services.
@matthewhaworth
8. Magento 2’s New Architecture
• Data persistence within service contracts starts with the ’repository’.
• “A Repository mediates between the domain and data mapping
layers, acting like an in-memory domain object collection.” – Martin
Fowler
@matthewhaworth
9. No more abstract model!
• Domain objects are now completely independent from the database!
@matthewhaworth
Model Abstract
Model
extends
10. @matthewhaworth
Magento 1
Magento 2
Model Abstract
Model
Resource Model
Abstract
Resource Model
extends extends
delegates database
map and save
Repository Interface
Repository
Implementation
implements
Data Interface
Data Object
Implementation
implements
is passed to
repository for
save
11. @matthewhaworth
Magento 1
Magento 2
Model Abstract
Model
Resource Model
Abstract
Resource Model
extends extends
delegates database
map and save
Resource Model
Abstract
Resource Model
extends
Repository Interface
Repository
Implementation
implements
Data Interface
Data Object
Implementation
implements
delegates
database map
and save
is passed to
repository for
save
12. Why move to repositories?
• Separate the representation of data, business logic and data
persistence
• Beneficial for testing by allowing a substitution point for unit tests
• Repository interfaces provides a version-able, single point of
communication for APIs and other modular dependencies
@matthewhaworth
13. But wait, there’s a problem…
The object passed to the resource must extend the Abstract Model
public function save(MagentoFrameworkModelAbstractModel $object)
@matthewhaworth
Resource ModelRepository InterfaceData Interface
14. So what are our options?
1. Implement data interface and extend the Abstract Model,
sacrificing our new found independence.
@matthewhaworth
Data Object
Abstract ModelData Interface
implements extends
15. So what are our options?
2. Implement the data interface and map to the Abstract Model in
the repository before passing to the resource.
@matthewhaworth
Abstract Model
Implementation
Data Object Repository Resource
map
16. So what are our options?
3. Best of both worlds!
Implement the data interface, the abstract model and map to the
Abstract Model in the repository before passing to the resource.
@matthewhaworth
Model & Data Object Repository Resource
2. Map to data object
Abstract ModelData Interface
implements extends
1. Submit to save
Model & Data Object
17. So what are our options?
4. Use a different data persistence layer to the Magento DB Resource,
maybe Doctrine?
@matthewhaworth
18. So what are our options?
4. Use a different data persistence layer to the Magento DB Resource,
maybe Doctrine?
@matthewhaworth
Nah.
19. For me, the clear winner is approach 3
• Implement the data interface and
extend the abstract model
• Map from the data interface to
the abstract model in the
repository
• Avoids duplicating an extra model
for the sake of pushing to the
resource
@matthewhaworth
Model & Data Object Repository
Resource
2. Map to data object
Abstract Model Data Interface
implementsextends
1. Submit to save
Model & Data Object
21. Where can I see good examples?
Magento_Customer was regarded as the best example.
This module maps its data interfaces to a separate Abstract Model
implementation in its repository (approach 2).
Multi Source Inventory (a set of modules) is currently regarded as the
best example to follow.
Data models in this module both implement the data interface and
extend the data model (approach 3) and also make use of CQRS.
(see MagentoInventoryModelStock @ github.com/magento-engcom/msi)
@matthewhaworth
22. What does the future look like?
• Removing the Abstract Model entirely
• Moving beforeSave(), afterSave(), etc to plugins and events (AOP)
(They’re also making them ‘bulk-first’.)
• Command Query Responsibility Segregation
@matthewhaworth
23. Thank you to Alan Kent, Anton Kril and Vinai Kopp
@matthewhaworth
Questions?