Install the Product Glue API

Edit on GitHub

This document describes how to install the Products Glue API.

Prerequisites

Install the required features:

NAME VERSION INSTALLATION GUIDE
Spryker Core 202410.0 Install the Spryker Core Glue API
Product 202410.0
Price 202410.0

1) Install the required modules

Install the required modules using composer:

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.1.0" --update-with-dependencies
Verification

Make sure 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 backward-compatibility reasons only.

3) Set up database schema and transfer objects

Update the database and generate entity and transfer changes:

console propel:install
console transfer:generate
Verification

Ensure that the following changes have occurred in transfer objects:

TRANSFER TYPE EVENT PATH
AbstractProductsRestAttributes class created src/Generated/Shared/Transfer/AbstractProductsRestAttributesTransfer
ConcreteProductsRestAttributes class created src/Generated/Shared/Transfer/ConcreteProductsRestAttributesTransfer
RestProductImageSetsAttributes class created src/Generated/Shared/Transfer/RestProductImageSetsAttributesTransfer
RestProductImageSet class created src/Generated/Shared/Transfer/RestProductImageSetTransfer
RestImagesAttributes class created src/Generated/Shared/Transfer/RestImagesAttributesTransfer
RestProductPriceAttributes class created src/Generated/Shared/Transfer/RestProductPriceAttributesTransfer
RestProductPricesAttributes class created src/Generated/Shared/Transfer/RestProductPricesAttributesTransfer
RestCurrency 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.

Reexport data to storage

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. Spryker\Glue\ProductsRestApi\Plugin
ConcreteProductsResourceRoutePlugin Registers the concrete-products resource. 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 list<\Spryker\Glue\GlueApplicationExtension\Dependency\Plugin\ResourceRoutePluginInterface>
     */
    protected function getResourceRoutePlugins(): array
    {
        return [
            new AbstractProductsResourceRoutePlugin(),
            new ConcreteProductsResourceRoutePlugin(),
        ];
    }
}
Verification

Ensure that the following endpoints are available:

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

  • https://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. Spryker\Glue\ProductsRestApi\Plugin\GlueApplication
ProductAbstractByProductAbstractSkuResourceRelationshipPlugin Adds the abstract-products resource as a relationship to the concrete-products resource. 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

Make sure the following applies:

  • The following endpoints are available:

    • https://glue.mysprykershop.com/abstract-products/{{abstract_sku}}
    • https://glue.mysprykershop.com/concrete-products/{{concrete_sku}}
  • When the concrete-products resource is included as a query string, the abstract-products resource returns it as a relationship: https://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: https://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. Spryker\Glue\ProductImageSetsRestApi\Plugin
ConcreteProductImageSetsRoutePlugin Registers the concrete-product-image-sets resource. Spryker\Glue\ProductImageSetsRestApi\Plugin
AbstractProductsProductImageSetsResourceRelationshipPlugin Adds the abstract-product-image-sets resource as a relationship to the abstract-products resource. Spryker\Glue\ProductImageSetsRestApi\Plugin\Relationship
ConcreteProductsProductImageSetsResourceRelationshipPlugin Adds the concrete-product-image-sets resource as a relationship to the concrete-products resource. 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 list<\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

Make sure the following applies:

  • The following endpoints are available:

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

    • https://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: https://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: https://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. Spryker\Glue\ProductPricesRestApi\Plugin
ConcreteProductPricesRoutePlugin Registers the concrete-product-prices resource. Spryker\Glue\ProductPricesRestApi\Plugin
AbstractProductPricesByResourceIdResourceRelationshipPlugin Adds the abstract-product-prices-resource as a relationship to the abstract-products resource. Spryker\Glue\ProductPricesRestApi\Plugin\GlueApplication
ConcreteProductPricesByResourceIdResourceRelationshipPlugin Adds the concrete-product-prices-resource as a relationship to the concrete-products resource. 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 list<\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

Make sure the following applies:

  • The following endpoints are available:

    • https://glue.mysprykershop.com/abstract-products/{{abstract_sku}}/abstract-product-prices
    • https://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: https://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: https://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. 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

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

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

Response sample
{  
   "data":{  
      "type":"abstract-products",
      "id":"001",
      "attributes":{  
         ...
      },
      "links":{  
         "self":"https://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":"https://glue.mysprykershop.com/category-nodes/4"
         }
      },
      {  
         "type":"category-nodes",
         "id":"2",
         "attributes":{  
            ...
         },
         "links":{  
            "self":"https://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. 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 list<\Spryker\Glue\GlueApplicationExtension\Dependency\Plugin\ResourceRoutePluginInterface>
     */
    protected function getResourceRoutePlugins(): array
    {
        return [
            new ProductManagementAttributesResourceRoutePlugin(),
        ];
    }
}
Verification

Make sure that the following endpoint is available: https://glue.mysprykershop.com/product-management-attributes/{{attribute_key}}

Enable multiselect product attributes

Activate the following plugins:

PLUGIN SPECIFICATION PREREQUISITES NAMESPACE
MultiSelectAttributeConcreteProductsResourceExpanderPlugin Formats the “multiselect” attributes of the concrete-products resource to string. Spryker\Glue\ProductAttributesRestApi\Plugin\ProductsRestApi
MultiSelectAttributeAbstractProductsResourceExpanderPlugin Formats the “multiselect” attributes of the abstract-products resource to string. Spryker\Glue\ProductAttributesRestApi\Plugin\ProductsRestApi

src/Pyz/Glue/ProductsRestApi/ProductsRestApiDependencyProvider.php

<?php

namespace Pyz\Glue\ProductsRestApi;

use Spryker\Glue\ProductAttributesRestApi\Plugin\ProductsRestApi\MultiSelectAttributeAbstractProductsResourceExpanderPlugin;
use Spryker\Glue\ProductAttributesRestApi\Plugin\ProductsRestApi\MultiSelectAttributeConcreteProductsResourceExpanderPlugin;
use Spryker\Glue\ProductsRestApi\ProductsRestApiDependencyProvider as SprykerProductsRestApiDependencyProvider;

class ProductsRestApiDependencyProvider extends SprykerProductsRestApiDependencyProvider
{
    /**
     * @return array<\Spryker\Glue\ProductsRestApiExtension\Dependency\Plugin\ConcreteProductsResourceExpanderPluginInterface>
     */
    protected function getConcreteProductsResourceExpanderPlugins(): array
    {
        return [
            new MultiSelectAttributeConcreteProductsResourceExpanderPlugin(), // remove if the project is accept product attribute values as array of strings
        ];
    }

    /**
     * @return array<\Spryker\Glue\ProductsRestApiExtension\Dependency\Plugin\AbstractProductsResourceExpanderPluginInterface>
     */
    protected function getAbstractProductsResourceExpanderPlugins(): array
    {
        return [
            new MultiSelectAttributeAbstractProductsResourceExpanderPlugin(), // remove if the project is accept product attribute values as array of strings
        ];
    }
}

Verification

Make sure that abstract-products and concrete-products resources return “multiselect” product attributes as strings.