Extending a REST API resource
Edit on GitHubSpryker Glue REST API comes with a set of predefined APIs out of the box. You have the possibility to extend and customize them to your own project needs. For this purpose, you need to extend the Glue API modules that provide the relevant functionality on your project level.
The following guide relies on your knowledge of the structure of a Glue REST API resource module and the behavior of its constituents. For more details, see the Resource Modules section in Glue Infrastructure.
Prerequisites
To complete this tutorial, you need to comply with the following prerequisites:
If you have a development virtual machine with the B2C Demo Shop installed, all the required components will be available out of the box.
Also, let us assume that you modified the product storage data to match your product requirements. For example, let’s assume that you added the manufacturerCountry
field to the product data not as an attribute, but as another field in the database.
For more details, see Database schema for product attributes and Extending the Database Schema.
Now, let us add this field to responses of the Products API endpoints:
1. Extend Glue transfers
First of all, we need to extend the existing Glue Transfers that describe Glue attributes. Attributes of Products resources are defined in a transfer file named products_rest_api.transfer.xml
. To extend it, do the following:
- Create file
src/Pyz/Shared/ProductsRestApi/Transfer/products_rest_api.transfer.xml
that will extend the transfer on the project level
All transfer file names end with .transfer.xml
.
- In the newly created file, define only the field(s) you want to add, in our case,
manufacturerCountry
:
Code sample
<?xml version="1.0"?>
<transfers xmlns="spryker:transfer-01"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="spryker:transfer-01 http://static.spryker.com/transfer-01.xsd">
<transfer name="AbstractProductsRestAttributes">
<property name="manufacturerCountry" type="string"/>
</transfer>
<transfer name="ConcreteProductsRestAttributes">
<property name="manufacturerCountry" type="string"/>
</transfer>
</transfers>
-
Run
vendor/bin/console transfer:generate
to generate the transfers. -
Check that the generated transfers contain the attribute you added:
src/Generated/Shared/Transfer/AbstractProductsRestAttributesTransfer.php - for abstract products
;src/Generated/Shared/Transfer/ConcreteProductsRestAttributesTransfer.php
- for concrete products;
You can also use a Spryk to extend Glue transfers. Run the following command:
console spryk:run AddSharedRestAttributesTransfer --mode=project --module=ResourcesRestApi --organization=Pyz --name=RestResourcesAttributes
2. Put data
If automatic transfer-to-transfer conversion can be performed, you do not need to take extra steps to put data in the attribute you added on step 1. Automatic conversion occurs when the attribute name defined in the REST transfer matches exactly the name of the respective field in the storage transfer.
In more complicated cases, when, for example, you need to pull data from alternative storage or map data differently from what auto-mapping does, you need to override the processor classes. Let us override the AbstractProductsResourceMapper
class in order to add the manufacturerCountry
attribute data. For this purpose, we need to extend, on the project level, the ProductsRestApi
module that implements the Products API. To do this:
- Create the
src/Pyz/Glue/ProductsRestApi
directory. - Implement
\Pyz\Glue\ProductsRestApi\Processor\Mapper\AbstractProductsResourceMapper
as follows:
AbstractProductsResourceMapper.php
<?php
namespace Pyz\Glue\ProductsRestApi\Processor\Mapper;
use Generated\Shared\Transfer\AbstractProductsRestAttributesTransfer;
use Spryker\Glue\ProductsRestApi\Processor\Mapper\AbstractProductsResourceMapper as SprykerAbstractProductsResourceMapper;
class AbstractProductsResourceMapper extends SprykerAbstractProductsResourceMapper
{
/**
* @param array $abstractProductData
*
* @return \Generated\Shared\Transfer\AbstractProductsRestAttributesTransfer
*/
public function mapAbstractProductsDataToAbstractProductsRestAttributes(array $abstractProductData): AbstractProductsRestAttributesTransfer
{
$restAbstractProductsAttributesTransfer = parent::mapAbstractProductsDataToAbstractProductsRestAttributes($abstractProductData);
$restAbstractProductsAttributesTransfer->setManufacturerCountry('Portugal');
return $restAbstractProductsAttributesTransfer;
}
}
As you can see from the code, the mapper that you implemented extends the original core mapper (located in Spryker\Glue\ProductsRestApi\Processor\Mapper\AbstractProductsResourceMapper
) and calls the parent method in the method we override. This way, we can avoid re-defining the whole class and define only the things we want to override.
You can also use a Spryk to put data. Run the following command:
console spryk:run AddGlueResourceMapper --mode=project --module=ResourcesRestApi --organization=Pyz --subDirectory=Mapper --className=Resource
This will create a mapper and add it to the factory on the project level. You will need to extend the mapper from the original feature.
3. Override mapper initialization
Now, we need to override the initialization of the mapper we created on the previous step. For this purpose, we need to extend the factory of the ProductsRestApi
module. A factory is used to create objects and processor classes of a module, thus, by overriding it, we can invoke our new mapper. To do this:
- Create the Glue factory on the project level:
\Pyz\Glue\ProductsRestApi\ProductsRestApiFactory
. - Implement the factory as follows:
ProductsRestApiFactory.php
<?php
namespace Pyz\Glue\ProductsRestApi;
use Pyz\Glue\ProductsRestApi\Processor\Mapper\AbstractProductsResourceMapper;
use Spryker\Glue\ProductsRestApi\Processor\Mapper\AbstractProductsResourceMapperInterface;
use Spryker\Glue\ProductsRestApi\ProductsRestApiFactory as SprykerProductsRestApiFactory;
class ProductsRestApiFactory extends SprykerProductsRestApiFactory
{
/**
* @return \Spryker\Glue\ProductsRestApi\Processor\Mapper\AbstractProductsResourceMapperInterface
*/
public function createAbstractProductsResourceMapper(): AbstractProductsResourceMapperInterface
{
return new AbstractProductsResourceMapper();
}
}
The same as the mapper, ProductsRestApiFactory
extends the core factory and only overrides the mapper creation.
You can also use a Spryk to override mapper initialization. Run the following command:
console spryk:run AddGlueMapperFactoryMethod --mode=project --module=ResourcesRestApi --organization=Pyz --subDirectory=Mapper --className=Resource
This will add mapper initialization to the project level factory.
4. Verify implementation
No, you can query the Products API to check whether the attribute has been added to the API response. For example, you can query information on one of the products with the manufacturerCountry
field populated. For details, see Retrieving abstract products and Retrieving concrete products.
Thank you!
For submitting the form