Understanding layered software architecture is essential for understanding basic Magento product organization. In this article we are going to provide a detailed explanation of each of the 4 layers in Magento 2 and the way they are used in Magento 2 application. After that we will take a close-up look at Service layer, there is a lot to talk about.
Magento 2 Architecture can be divided into the following layers:
- Presentation layer;
- Service layer;
- Domain layer;
- Persistence layer.
These layers, that also include components, are demonstrated on the following diagram:
Presentation Layer
Presentation layer includes a view of the administrative part of the site, an API call, and a view for site users. This level consists of such components as layouts, blocks, templates and controllers. The view code controls the user/administrator interaction with the store and its appearance. Presentation layer components call the Service layer, which in its turn sends queries to Domain layer.
Service Layer
Service layer serves as a bridge between Presentation layer and Domain layer. This is implemented using service contracts, which are defined using PHP interfaces. All the calls from web service interfaces (API) or users (controllers) are routed through Service layer. This allows you to separate the business logic from the code. Service contract includes:
- Controllers;
- Web services (SOAP and REST API calls);
- Third-party modules using service contracts.
Domain Layer
Domain layer contains the level of the module’s business logic. It usually does not contain the information specific to a particular resource or database. Its main functions include:
- identifying common Magento data objects or models that contain business logic;
- (optional) implementation of service contracts.
Persistence Layer
Magento uses the “active record” pattern for saving. In Magento, the model object contains a “resource model” that compares the object with one or more database records. “Resource model” is responsible for performing such functions as:
- Executing all CRUD requests. The resource model contains the SQL code for executing these queries;
- Performing additional business logic. For example, a resource model can perform data validation, run processes before or after saving data, or perform other operations on the database.
If you expect to return multiple items from a database query, you must implement a special type of “Resource model”, known as “collection”. “Collection” is a class that loads several models into a structure similar to an array, based on a set of rules.
Now let us take a closer look at Service layer in Magento 2.
Magento 2 Service Layer
Service layer In Magento 2 is a new layer that lies between Presentation layer and the business logic. The goal is to make all calls from other modules, as well calls from Presentation layer (blocks, templates and controllers) pass through Service layer. Besides that, Service layer can be easily opened as a REST web service or a SOAP endpoint.
Service layer for the module is a set of PHP interfaces, data types, and the implementation of these interfaces. Let’s take the Customer Interface class code as an example, with the names of the fields of the entity being a constant, and the methods get () and set () serving to write data in the entity table and the module’s attributes. Also note that in PHPDoc we define the type of the field value. We describe the fields of the user object as following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<?php namespace Magento\Customer\Api\Data; interface CustomerInterface extends \Magento\Framework\Api\CustomAttributesDataInterface { ... const FIRSTNAME = 'firstname'; ... /** * Get first name * * @return string */ public function getFirstname(); /** * Set first name * * @param string $firstname * @return $this */ public function setFirstname($firstname); ... |
To implement CRUD in Magento 2, we need to describe the repository interface and implement it. We can take the Customer Repository Interface as an example, which describes the methods of working with the customer object. As you can see, this implementation simplifies the work with different versions of the module, since we have one entry point through the API and the implementation is separated. If a new mandatory field is added to the entity, it is going to be an exceptional case.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<?php /** * * Copyright (c) Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Customer\Api; /** * Customer CRUD interface. * @api * @since 100.0.2 */ interface CustomerRepositoryInterface { /** * Create or update a customer. * * @param \Magento\Customer\Api\Data\CustomerInterface $customer * @param string $passwordHash * @return \Magento\Customer\Api\Data\CustomerInterface * @throws \Magento\Framework\Exception\InputException If bad input is provided * @throws \Magento\Framework\Exception\State\InputMismatchException If the provided email is already used * @throws \Magento\Framework\Exception\LocalizedException */ public function save(\Magento\Customer\Api\Data\CustomerInterface $customer, $passwordHash = null); ... |
Service layer also includes Management interfaces, which provide management functions, not associated with the repositories. They do not perform any operations to change the data. Let’s consider the example of Account Management Interface:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<?php /** * * Copyright (c) Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Customer\Api; /** * Interface for managing customers accounts. * @api * @since 100.0.2 */ interface AccountManagementInterface { .... /** * Check if customer can be deleted. * * @api * @param int $customerId * @return bool * @throws \Magento\Framework\Exception\NoSuchEntityException If group is not found * @throws \Magento\Framework\Exception\LocalizedException */ public function isReadonly($customerId); .... |
Service layer also includes Metadata interfaces. Metadata is data, that describes other data. To see the example of this interface, let’s look at the Address Metadata Interface:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<?php /** * Copyright (c) Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Customer\Api; /** * Interface for retrieval information about customer address attributes metadata. * @api * @since 100.0.2 */ interface AddressMetadataInterface extends MetadataInterface { const ATTRIBUTE_SET_ID_ADDRESS = 2; const ENTITY_TYPE_ADDRESS = 'customer_address'; const DATA_INTERFACE_NAME = \Magento\Customer\Api\Data\AddressInterface::class; } |
Service layer is not mandatory, however, Magento developers recommend it for developing your modules. Magento developers plan to convert all their internal modules to using this layer. Its usage leads to a slight loss of productivity, which is insignificant compared to the advantages of this approach.