In Magento 2, is there a concrete example of something that's built using the Service Contract concept? I've seen this term thrown around a lot, but looking at Magento 2 as it exists now it's not clear to me if Service Contracts are more guiding principles, or if they actually tie back to specific implementations of things in Magento 2.
As I understand it all the interfaces defined in the Api folder are the Service Contracts. So anywhere the interface is used instead of the actual implementation of the class it uses the Service Contract.
An example would be this plugin implementation here https://github.com/magento/magento2/blob/2.3.2/app/code/Magento/GiftMessage/Model/Plugin/OrderGet.php#L78
protected function getOrderGiftMessage(\Magento\Sales\Api\Data\OrderInterface $order)
Services (also called service contracts) are one of our core development patterns in Magento 2 to ensure stable interfaces for easy customization/extension. They take 2 forms in the code base ( both are annotated with
@api on the class or class methods to identify them as stable interfaces that you can customize and or expose as a web API ): API or SPI. The API's are defined in the API folder and take up two forms - a fully refactored service and just an API only module.
Fully refactored services are reflected in Customer, Inventory, Tax, and Quote* modules (Customer being the service to emulate, Quote has a areas remaining that need to be refactored). An API only module can be seen in Catalog, Sales and CMS. For fully refactored services you should only have to do a plugin on the service method to impact both web apis and the GUI. For API only modules you'd need to plugin on service method to impact web apis but would still need to do 1x style customizations to impact the GUI.
SPI's are basically interfaces within the code annotated with
@api that are intended spots that 3rd parties would implement to provide some business functionality. An example of an SPI (
CarrierInterface) defined in the Shipping module that you'd implement in your shipping module (i.e. Ups ).
The service framework provides a number of interesting advantages. Easy exposure as a web api (and coming post 2.0 via message queues) vi
webapi.xml configuration (as SOAP and REST style). In the near term (post 2.0) we'll be adding API call outs (sync calls, or Webhooks if configured to fire async, messages out) that can all be managed/exposed via configuration. Safer install/upgrades - you can programmatically identify problem situations ( 2 or more extensions implementing the same interface ). Streamlined customization that impacts both web apis and gui as there's just one method/service to customize ( for fully refactored module or new modules/services created by the community ).
Magento service contracts
Essentially, service contracts are just a set of interfaces and classes that protect data integrity and hide the business logic. The reason why customers will want to use this is that the contract allows the service to evolve without affecting its users.
The reason this upgrade is important is because it changes the way that users interact with different modules. In Magento 1, there were no good ways of interacting with other modules. With service contracts in Magento 2, you can access and manipulate data easily, without having to worry about the system’s structure.
Service contract architecture
The service layer has two different interface types: Data interfaces and Service interfaces. Data interfaces are objects that preserve data integrity by using the following patterns:
They’re read-only, since they only define constants and getters. Getter functions can contain no parameters. A getter function can only return a simple object type (string, integer, Boolean), a simple type array, and another data interface. Mixed types can’t be returned by getter functions. Data entity builders are the only way to populate and modify data interfaces.
Service interfaces provide a set of public methods that a client can use. There are three service interfaces subtypes:
Repository Interfaces Management Interfaces Metadata Interfaces
Repository interfaces ensure that a user can access persistent data entities. For example, persistent data entities within the Customer Module are Consumer, Address, and Group. This gives us three different interfaces:
CustomerRepositoryInterface AddressRepositoryInterface GroupRepositoryInterface
The methods that these interfaces have are:
Save – If there’s no ID, creates a new record, and updates what’s existing if there is one. Get – Looks for the IDs in the database and returns a certain data entity interface. GetList – Finds all data entities that correspond with the search criteria, then gives access to the matches by returning the search result interface. Delete – Deletes the selected entity DeleteById – Deletes the entity when you only have its key.
These interfaces contain different management functions that are unrelated to repositories. Here are some examples:
AccountManagementInterface contains functions such as createAccount(), isEmailAvailable(), changePassword(), and activate(). AddressManagementInterface checks whether an address is valid by using the validate() function.
The number of patterns is constantly growing, and as it does so, some of these functions are likely to be added to them.
Metadata interfaces give information about all the attributes that are defined for a specific entity. This also includes custom attributes, which you can access with the getCustomAttribute($name) function. These custom attributes include:
EAV attributes – Defined via the administration interface for a local site. They can differ according to the site, which means that they can’t be represented in the data entity interface written in PHP. Extension attributes, for which the extension modules are used.