Glue API - Product feature integration

Edit on GitHub

Follow the steps below to integrate the Glue API: Products feature.

Prerequisites

To start feature integration, overview and install the necessary features:

NAME VERSION INTEGRATION GUIDE
Spryker Core 202108.0 Glue API: Spryker Core feature integration
Product 202108.0
Price 202108.0

1) Install the required modules using Composer

Run the following command to install the required modules:

composer require spryker/products-rest-api:"^2.11.0" spryker/product-image-sets-rest-api:"^1.0.3" spryker/product-prices-rest-api:"^1.1.0" spryker/product-tax-sets-rest-api:"^2.1.2" spryker/products-categories-resource-relationship:"^1.0.0" spryker/product-attributes-rest-api:"^1.0.0" --update-with-dependencies
Verification

Make sure that the following modules have been installed:

MODULE EXPECTED DIRECTORY
ProductsRestApi vendor/spryker/products-rest-api
ProductImageSetsRestApi vendor/spryker/product-image-sets-rest-api
ProductPricesRestApi vendor/spryker/product-prices-rest-api
ProductTaxSetsRestApi vendor/spryker/product-tax-sets-rest-api
ProductsCategoriesResourceRelationship vendor/spryker/products-categories-resource-relationship
ProductAttributesRestApi vendor/spryker/product-attributes-rest-api

2) Set up configuration

You can control whether the abstract-products get the concrete-products as a relationship by default with the ProductsRestApiConfig::ALLOW_PRODUCT_CONCRETE_EAGER_RELATIONSHIP config setting.

src/Pyz/Glue/ProductsRestApi/ProductsRestApiConfig.php

<?php

namespace Pyz\Glue\ProductsRestApi;

use Spryker\Glue\ProductsRestApi\ProductsRestApiConfig as SprykerProductsRestApiConfig;

class ProductsRestApiConfig extends SprykerProductsRestApiConfig
{
    public const ALLOW_PRODUCT_CONCRETE_EAGER_RELATIONSHIP = false;
}

We recommend setting ALLOW_PRODUCT_CONCRETE_EAGER_RELATIONSHIP to false.  

Using ALLOW_PRODUCT_CONCRETE_EAGER_RELATIONSHIP = true in combination with ConcreteProductsByProductConcreteIdsResourceRelationshipPlugin, which is described later in this document, results in duplicated relationships.

We also recommend using ConcreteProductsByProductConcreteIdsResourceRelationshipPlugin with ALLOW_PRODUCT_CONCRETE_EAGER_RELATIONSHIP = false. The config setting exists for BC reasons only.

3) Set up database schema and transfer objects

Run the following commands to update the database and generate entity and transfer changes:

console transfer:generate
console propel:install
console transfer:generate
Verification

Ensure that the following changes have occurred in transfer objects:

TRANSFER TYPE EVENT PATH
AbstractProductsRestAttributesTransfer class created src/Generated/Shared/Transfer/AbstractProductsRestAttributesTransfer
ConcreteProductsRestAttributesTransfer class created src/Generated/Shared/Transfer/ConcreteProductsRestAttributesTransfer
RestProductImageSetsAttributesTransfer class created src/Generated/Shared/Transfer/RestProductImageSetsAttributesTransfer
RestProductImageSetTransfer class created src/Generated/Shared/Transfer/RestProductImageSetTransfer
RestImagesAttributesTransfer class created src/Generated/Shared/Transfer/RestImagesAttributesTransfer
RestProductPriceAttributesTransfer class created src/Generated/Shared/Transfer/RestProductPriceAttributesTransfer
RestProductPricesAttributesTransfer class created src/Generated/Shared/Transfer/RestProductPricesAttributesTransfer
RestCurrencyTransfer class created src/Generated/Shared/Transfer/RestCurrencyTransfer
RestProductManagementAttributeAttributes class created src/Generated/Shared/Transfer/RestProductManagementAttributeAttributesTransfer
RestLocalizedProductManagementAttributeKeyAttributes class created src/Generated/Shared/Transfer/RestLocalizedProductManagementAttributeKeyAttributesTransfer
RestProductManagementAttributeValueAttributes class created src/Generated/Shared/Transfer/RestProductManagementAttributeValueAttributesTransfer
RestProductManagementAttributeValueTranslationAttributes class created src/Generated/Shared/Transfer/RestProductManagementAttributeValueTranslationAttributesTransfer
Verification

Ensure that SpyProductAbstractStorage and SpyProductConcreteStorage are extended with the synchronization behavior of the following methods:

ENTITY TYPE EVENT PATH METHODS
SpyProductAbstractStorage class extended src/Orm/Zed/ProductStorage/Persistence/Base/SpyProductAbstractStorage syncPublishedMessageForMappings(), syncUnpublishedMessageForMappings()
SpyProductConcreteStorage class extended src/Orm/Zed/ProductStorage/Persistence/Base/SpyProductConcreteStorage syncPublishedMessageForMappings(), syncUnpublishedMessageForMappings()

4) Set up behavior

Set up the following behaviors.

Re-export data to storage

Run the following commands to reload the abstract and concrete product data into the Storage:

console publish:trigger-events -r product_abstract
console publish:trigger-events -r product_concrete
Verification

Ensure that the following Redis keys exist, and there is data in them:

  • kv:product_abstract:{{store_name}}:{{locale_name}}:sku:{{sku_product_abstract}}

  • kv:product_concrete:{{locale_name}}:sku:{{sku_product_concrete}}

Enable resources

Activate the following plugins:

PLUGIN SPECIFICATION PREREQUISITES NAMESPACE
AbstractProductsResourceRoutePlugin Registers the abstract-products resource. None Spryker\Glue\ProductsRestApi\Plugin
ConcreteProductsResourceRoutePlugin Registers the concrete-products resource. None Spryker\Glue\ProductsRestApi\Plugin

src/Pyz/Glue/GlueApplication/GlueApplicationDependencyProvider.php

<?php

namespace Pyz\Glue\GlueApplication;

use Spryker\Glue\GlueApplication\GlueApplicationDependencyProvider as SprykerGlueApplicationDependencyProvider;
use Spryker\Glue\ProductsRestApi\Plugin\AbstractProductsResourceRoutePlugin;
use Spryker\Glue\ProductsRestApi\Plugin\ConcreteProductsResourceRoutePlugin;

class GlueApplicationDependencyProvider extends SprykerGlueApplicationDependencyProvider
{
    /**
     * @return \Spryker\Glue\GlueApplicationExtension\Dependency\Plugin\ResourceRoutePluginInterface[]
     */
    protected function getResourceRoutePlugins(): array
    {
        return [
            new AbstractProductsResourceRoutePlugin(),
			new ConcreteProductsResourceRoutePlugin(),
        ];
    }
}
Verification

Ensure that the following endpoints are available:

  • http://glue.mysprykershop.com/abstract-products/{{abstract_sku}}

  • http://glue.mysprykershop.com/concrete-products/{{concrete_sku}}

Enable relationships

Activate the following plugins:

PLUGIN SPECIFICATION PREREQUISITES NAMESPACE
ConcreteProductsByProductConcreteIdsResourceRelationshipPlugin Adds the concrete-products resource as a relationship to the abstract-products resource. None Spryker\Glue\ProductsRestApi\Plugin\GlueApplication
ProductAbstractByProductAbstractSkuResourceRelationshipPlugin Adds the abstract-products resource as a relationship to the concrete-products resource. None Spryker\Glue\ProductsRestApi\Plugin\GlueApplication

src/Pyz/Glue/GlueApplication/GlueApplicationDependencyProvider.php

<?php

namespace Pyz\Glue\GlueApplication;

use Spryker\Glue\GlueApplication\GlueApplicationDependencyProvider as SprykerGlueApplicationDependencyProvider;
use Spryker\Glue\GlueApplicationExtension\Dependency\Plugin\ResourceRelationshipCollectionInterface;
use Spryker\Glue\ProductsRestApi\Plugin\GlueApplication\ConcreteProductsByProductConcreteIdsResourceRelationshipPlugin;
use Spryker\Glue\ProductsRestApi\Plugin\GlueApplication\ProductAbstractByProductAbstractSkuResourceRelationshipPlugin;
use Spryker\Glue\ProductsRestApi\ProductsRestApiConfig;

class GlueApplicationDependencyProvider extends SprykerGlueApplicationDependencyProvider
{
    /**
     * @param \Spryker\Glue\GlueApplicationExtension\Dependency\Plugin\ResourceRelationshipCollectionInterface $resourceRelationshipCollection
     *
     * @return \Spryker\Glue\GlueApplicationExtension\Dependency\Plugin\ResourceRelationshipCollectionInterface
     */
    protected function getResourceRelationshipPlugins(
        ResourceRelationshipCollectionInterface $resourceRelationshipCollection
    ): ResourceRelationshipCollectionInterface {
        $resourceRelationshipCollection->addRelationship(
            ProductsRestApiConfig::RESOURCE_ABSTRACT_PRODUCTS,
            new ConcreteProductsByProductConcreteIdsResourceRelationshipPlugin()
        );
        $resourceRelationshipCollection->addRelationship(
            ProductsRestApiConfig::RESOURCE_CONCRETE_PRODUCTS,
            new ProductAbstractByProductAbstractSkuResourceRelationshipPlugin()
        );

        return $resourceRelationshipCollection;
    }
}
Verification

Ensure that:

  • The following endpoints are available:

  • When the concrete-products resource is included as a query string, the abstract-products resource returns it as a relationship: http://glue.mysprykershop.com/abstract-products/{{abstract_sku}}?include=concrete-products.

  • When the abstract-products resource is included as a query string, the concrete-products resource returns it as a relationship: http://glue.mysprykershop.com/concrete-products/{{concrete_sku}}?include=abstract-products.

Enable resources and relationships of image sets

Activate the following plugins:

PLUGIN SPECIFICATION PREREQUISITES NAMESPACE
AbstractProductImageSetsRoutePlugin Registers the abstract-product-image-sets resource. None Spryker\Glue\ProductImageSetsRestApi\Plugin
ConcreteProductImageSetsRoutePlugin Registers the concrete-product-image-sets resource. None Spryker\Glue\ProductImageSetsRestApi\Plugin
AbstractProductsProductImageSetsResourceRelationshipPlugin Adds the abstract-product-image-sets resource as a relationship to the abstract-products resource. None Spryker\Glue\ProductImageSetsRestApi\Plugin\Relationship
ConcreteProductsProductImageSetsResourceRelationshipPlugin Adds the concrete-product-image-sets resource as a relationship to the concrete-products resource. None Spryker\Glue\ProductImageSetsRestApi\Plugin\Relationship
src/Pyz/Glue/GlueApplication/GlueApplicationDependencyProvider.php
<?php

namespace Pyz\Glue\GlueApplication;

use Spryker\Glue\GlueApplication\GlueApplicationDependencyProvider as SprykerGlueApplicationDependencyProvider;
use Spryker\Glue\GlueApplicationExtension\Dependency\Plugin\ResourceRelationshipCollectionInterface;
use Spryker\Glue\ProductImageSetsRestApi\Plugin\AbstractProductImageSetsRoutePlugin;
use Spryker\Glue\ProductImageSetsRestApi\Plugin\ConcreteProductImageSetsRoutePlugin;
use Spryker\Glue\ProductImageSetsRestApi\Plugin\Relationship\AbstractProductsProductImageSetsResourceRelationshipPlugin;
use Spryker\Glue\ProductImageSetsRestApi\Plugin\Relationship\ConcreteProductsProductImageSetsResourceRelationshipPlugin;
use Spryker\Glue\ProductsRestApi\ProductsRestApiConfig;

class GlueApplicationDependencyProvider extends SprykerGlueApplicationDependencyProvider
{
    /**
     * @return \Spryker\Glue\GlueApplicationExtension\Dependency\Plugin\ResourceRoutePluginInterface[]
     */
    protected function getResourceRoutePlugins(): array
    {
        return [
            new AbstractProductImageSetsRoutePlugin(),
			new ConcreteProductImageSetsRoutePlugin(),
        ];
    }

 	/**
    * @param \Spryker\Glue\GlueApplicationExtension\Dependency\Plugin\ResourceRelationshipCollectionInterface $resourceRelationshipCollection
    *
    * @return \Spryker\Glue\GlueApplicationExtension\Dependency\Plugin\ResourceRelationshipCollectionInterface
    */
    protected function getResourceRelationshipPlugins(
        ResourceRelationshipCollectionInterface $resourceRelationshipCollection
    ): ResourceRelationshipCollectionInterface {
        $resourceRelationshipCollection->addRelationship(
            ProductsRestApiConfig::RESOURCE_ABSTRACT_PRODUCTS,
            new AbstractProductsProductImageSetsResourceRelationshipPlugin()
        );
        $resourceRelationshipCollection->addRelationship(
            ProductsRestApiConfig::RESOURCE_CONCRETE_PRODUCTS,
            new ConcreteProductsProductImageSetsResourceRelationshipPlugin()
        );

        return $resourceRelationshipCollection;
    }
}
Verification

Ensure the following:

  • The endpoints are available:

    • http://glue.mysprykershop.com/abstract-products/{{abstract_sku}}/abstract-product-image-sets

    • http://glue.mysprykershop.com/concrete-products/{{concrete_sku}}/concrete-product-image-sets

  • When the abstract-product-image-sets resource is included as a query string, the abstract-products resource returns it as a relationship: http://glue.mysprykershop.com/abstract-products/{{abstract_sku}}?include=abstract-product-image-sets

  • When the concrete-product-image-sets resource is included as a query string, the concrete-products resource returns it as a relationship: http://glue.mysprykershop.com/concrete-products/{{abstract_sku}}?include=concrete-product-image-sets

Enable resources and relationships of prices

Activate the following plugins:

PLUGIN SPECIFICATION PREREQUISITES NAMESPACE
AbstractProductPricesRoutePlugin Registers the abstract-product-prices resource. None Spryker\Glue\ProductPricesRestApi\Plugin
ConcreteProductPricesRoutePlugin Registers the concrete-product-prices resource. None Spryker\Glue\ProductPricesRestApi\Plugin
AbstractProductPricesByResourceIdResourceRelationshipPlugin Adds the abstract-product-prices-resource as a relationship to the abstract-products resource. None Spryker\Glue\ProductPricesRestApi\Plugin\GlueApplication
ConcreteProductPricesByResourceIdResourceRelationshipPlugin Adds the concrete-product-prices-resource as a relationship to the concrete-products resource. None Spryker\Glue\ProductPricesRestApi\Plugin\GlueApplication
src/Pyz/Glue/GlueApplication/GlueApplicationDependencyProvider.php
<?php

namespace Pyz\Glue\GlueApplication;

use Spryker\Glue\GlueApplication\GlueApplicationDependencyProvider as SprykerGlueApplicationDependencyProvider;
use Spryker\Glue\GlueApplicationExtension\Dependency\Plugin\ResourceRelationshipCollectionInterface;
use Spryker\Glue\ProductPricesRestApi\Plugin\AbstractProductPricesRoutePlugin;
use Spryker\Glue\ProductPricesRestApi\Plugin\ConcreteProductPricesRoutePlugin;
use Spryker\Glue\ProductPricesRestApi\Plugin\GlueApplication\AbstractProductPricesByResourceIdResourceRelationshipPlugin;
use Spryker\Glue\ProductPricesRestApi\Plugin\GlueApplication\ConcreteProductPricesByResourceIdResourceRelationshipPlugin;
use Spryker\Glue\ProductsRestApi\ProductsRestApiConfig;

class GlueApplicationDependencyProvider extends SprykerGlueApplicationDependencyProvider
{
    /**
     * @return \Spryker\Glue\GlueApplicationExtension\Dependency\Plugin\ResourceRoutePluginInterface[]
     */
    protected function getResourceRoutePlugins(): array
    {
        return [
            new AbstractProductPricesRoutePlugin(),
            new ConcreteProductPricesRoutePlugin(),
        ];
    }

    /**
     * @param \Spryker\Glue\GlueApplicationExtension\Dependency\Plugin\ResourceRelationshipCollectionInterface $resourceRelationshipCollection
     *
     * @return \Spryker\Glue\GlueApplicationExtension\Dependency\Plugin\ResourceRelationshipCollectionInterface
     */
    protected function getResourceRelationshipPlugins(
        ResourceRelationshipCollectionInterface $resourceRelationshipCollection
    ): ResourceRelationshipCollectionInterface {
        $resourceRelationshipCollection->addRelationship(
            ProductsRestApiConfig::RESOURCE_ABSTRACT_PRODUCTS,
            new AbstractProductPricesByResourceIdResourceRelationshipPlugin()
        );
        $resourceRelationshipCollection->addRelationship(
            ProductsRestApiConfig::RESOURCE_CONCRETE_PRODUCTS,
            new ConcreteProductPricesByResourceIdResourceRelationshipPlugin()
        );

        return $resourceRelationshipCollection;
    }
}
Verification

Ensure the following:

  • The endpoints are available:

    • http://glue.mysprykershop.com/abstract-products/{{abstract_sku}}/abstract-product-prices

    • http://glue.mysprykershop.com/concrete-products/{{concrete_sku}}/concrete-product-prices

  • When the abstract-product-prices resource is included as a query string, the abstract-products resource returns it as a relationship: http://glue.mysprykershop.com/abstract-products/{{abstract_sku}}?include=abstract-product-prices

  • When the concrete-product-prices resource is included as a query string, the concrete-products resource returns it as a relationship: http://glue.mysprykershop.com/concrete-products/{{abstract_sku}}?include=concrete-product-prices

Enable resources and relationships of category

Activate the following plugin:

PLUGIN SPECIFICATION PREREQUISITES NAMESPACE
AbstractProductsCategoriesResourceRelationshipPlugin Adds the categories resource as a relationship to the abstract-products resource. None Spryker\Glue\ProductsCategoriesResourceRelationship\Plugin

src/Pyz/Glue/GlueApplication/GlueApplicationDependencyProvider.php

<?php

namespace Pyz\Glue\GlueApplication;

use Spryker\Glue\GlueApplication\GlueApplicationDependencyProvider as SprykerGlueApplicationDependencyProvider;
use Spryker\Glue\GlueApplicationExtension\Dependency\Plugin\ResourceRelationshipCollectionInterface;
use Spryker\Glue\ProductsCategoriesResourceRelationship\Plugin\AbstractProductsCategoriesResourceRelationshipPlugin;
use Spryker\Glue\ProductsRestApi\ProductsRestApiConfig;

class GlueApplicationDependencyProvider extends SprykerGlueApplicationDependencyProvider
{
   /**
    * @param \Spryker\Glue\GlueApplicationExtension\Dependency\Plugin\ResourceRelationshipCollectionInterface $resourceRelationshipCollection
    *
    * @return \Spryker\Glue\GlueApplicationExtension\Dependency\Plugin\ResourceRelationshipCollectionInterface
    */
    protected function getResourceRelationshipPlugins(
        ResourceRelationshipCollectionInterface $resourceRelationshipCollection
    ): ResourceRelationshipCollectionInterface {
        $resourceRelationshipCollection->addRelationship(
            ProductsRestApiConfig::RESOURCE_ABSTRACT_PRODUCTS,
            new AbstractProductsCategoriesResourceRelationshipPlugin()
        );

        return $resourceRelationshipCollection;
    }
}
Verification

Ensure that the relationship has been registered correctly:

  1. Send a request to http://glue.mysprykershop.com/abstract-products/{{abstract_sku}}?include=category-nodes.

  2. The response should contain the category-nodes resource as a relationship.

Response sample
{  
   "data":{  
      "type":"abstract-products",
      "id":"001",
      "attributes":{  
         ...
      },
      "links":{  
         "self":"http://glue.mysprykershop.com/abstract-products/001"
      },
      "relationships":{  
         "category-nodes":{  
            "data":[  
               {  
                  "type":"category-nodes",
                  "id":"4"
               },
               {  
                  "type":"category-nodes",
                  "id":"2"
               }
            ]
         }
      }
   },
   "included":[  
      {  
         "type":"category-nodes",
         "id":"4",
         "attributes":{  
            ...
         },
         "links":{  
            "self":"http://glue.mysprykershop.com/category-nodes/4"
         }
      },
      {  
         "type":"category-nodes",
         "id":"2",
         "attributes":{  
            ...
         },
         "links":{  
            "self":"http://glue.mysprykershop.com/category-nodes/2"
         }
      }
   ]
}

Enable resources and relationships of product management attributes

Activate the following plugin:

PLUGIN SPECIFICATION PREREQUISITES NAMESPACE
ProductManagementAttributesResourceRoutePlugin Registers the product-management-attributes resource. None Spryker\Glue\ProductAttributesRestApi\Plugin\GlueApplication

src/Pyz/Glue/GlueApplication/GlueApplicationDependencyProvider.php

<?php

namespace Pyz\Glue\GlueApplication;

use Spryker\Glue\GlueApplication\GlueApplicationDependencyProvider as SprykerGlueApplicationDependencyProvider;
use Spryker\Glue\ProductAttributesRestApi\Plugin\GlueApplication\ProductManagementAttributesResourceRoutePlugin;

class GlueApplicationDependencyProvider extends SprykerGlueApplicationDependencyProvider
{
    /**
     * @return \Spryker\Glue\GlueApplicationExtension\Dependency\Plugin\ResourceRoutePluginInterface[]
     */
    protected function getResourceRoutePlugins(): array
    {
        return [
			new ProductManagementAttributesResourceRoutePlugin(),
        ];
    }
}
Verification

Ensure that the following endpoint is available: http://glue.mysprykershop.com/product-management-attributes/{{attribute_key}}