Skip to main content

Configuration

Clean-Up

After you've installed the Ecommerce Bundle with in a earlier setup, you need to clean up the default configuration.

  • Remove OpenDxp\Ecommerce\Bundle\FrontendBundle\EcommerceFrontendBundle::class from your config\bundles.php
  • Remove opendxp.security.password_hasher_factories from config/packages/opendxp.yaml
  • Remove parameters.opendxp_ecommerce.security.frontend_regex from config/packages/security.yaml
  • Remove providers.opendxp_ecommerce_user from config/packages/security.yaml
  • Remove firewalls.opendxp_ecommerce_frontend from config/packages/security.yaml
  • Remove %opendxp_ecommerce.security.frontend_regex%/_partial from config/packages/security.yaml in access_control

Installation

Then, proceed with the installation of the Headless Ecommerce Bundle:

Security

# packages/security.yaml
security:

providers:

# [...]

guest_provider:
id: OpenDxp\Bundle\HeadlessEcommerceBundle\Security\GuestProvider

firewalls:

# [...]

# Ecommerce Headless Bundle Firewall
# >> must be added BEFORE headless_api and AFTER opendxp_admin firewall
ecommerce_guest: '%opendxp_headless_ecommerce_bundle.guest_firewall_settings%'

# [...]

User Class

We need to enrich our user entity with Ecommerce user entity.

  • Make your user class implementation (e.g. App\Model\ApiUser) extending from \OpenDxp\Bundle\HeadlessEcommerceBundle\Model\ApiUser
  • Make your user class interface (e.g. App\Model\ApiUserInterface) extending from \OpenDxp\Bundle\HeadlessEcommerceBundle\Model\ApiUserInterface
  • Copy field customer from EcommerceUser class into to your user class definition
  • Delete fields firstname and lastname in your user class definition
  • Delete EcommerceUser class
  • Add the email validation rule for the endpoint to change the login identifier. See opendxp-headless docs for details.

Customer Class

Make sure the data object class EcommerceCustomer implements interface \OpenDxp\Bundle\HeadlessEcommerceBundle\Model\CustomerInterface (either in class definition or in your inheritance hierarchy)

Add field token to EcommerceCustomerClass:

  • Location: In tab information at first position
  • Type: Input
  • Unique: true
  • Editable: false

Product Class

Make sure the data object EcommerceProduct implements the interface \OpenDxp\Bundle\HeadlessEcommerceBundle\Model\ProductInterface (either in class definition or in your inheritance hierarchy).

Attribute Group Class

Adjust class EcommerceAttributeGroup:

General Settings:

  • Implements interface(s): \OpenDxp\Bundle\HeadlessEcommerceBundle\Model\AttributeGroupInterface

Add field displayType:

  • Type: Select
  • Options Source: Configure
  • Select Option Values: list, range

Add field unit:

  • Type: Input

Attributes Builder

[!NOTE]
This is an optional feature. If you want to use the product attributes builder, there are some additional steps to be done.

Make sure the data object EcommerceProduct implements the interface \OpenDxp\Bundle\HeadlessEcommerceBundle\Model\ProductAttributeSetAwareInterface (either in class definition or in your inheritance hierarchy).

Create Ecommerce Attribute Set Class

create class EcommerceAttributeSet with fields:

  • textfield:name (localized)
  • opendxp_ecommerce:relations:attributeGroups (stack: opendxp_ecommerce.attribute_group))

Modify Product Class

  • add field with name attributeSet and type manyToOneRelation (in tab attribute), allow EcommerceAttributeSet
  • add field with name attributesBuilder and type ecommerceProductAttributesBuilder (in tab attribute)
  • set fields to hidden:
    • attributeSet
    • allowedAttributeGroups
    • attributes

Add Translations

labeldeen
opendxp_ecommerce.attribute_setSetSet
opendxp_ecommerce.attribute_set.attribute_groupAttribut-GruppeAttribute Group
opendxp_ecommerce.attribute_set.attribute_groupsAttribut-GruppenAttribute Grupps
opendxp_ecommerce.attribute_set.attributesAttributeAttributes
opendxp_ecommerce.attribute_set.create_new_attributeNeues Attribut erstellenCreate new Attribute
opendxp_ecommerce.attribute_set.nameAttribut Set NameAttribute Set Name

Routes

Remove all Ecommerce static routes which comes by default after ecommerce bundle installation, except:

  • opendxp_ecommerce_product_detail
  • opendxp_ecommerce_category_list

[!NOTE]
No static routes will be installed if the EcommerceFrontendBundle is not installed. Add the routes manually:

# backend/app/var/config/staticroutes/opendxp_ecommerce_category_list.yaml
opendxp_static_routes:
definitions:
opendxp_ecommerce_category_list:
name: opendxp_ecommerce_category_list
pattern: '/(\b(?!admin\b)[a-zA-Z0-9-_]+)\/category\/(.*?)\~c([0-9]+)$/'
reverse: /%%_locale/category/%%name-c%category
controller: App\Controller\HeadlessController::nullAction
variables: '_locale,name,category'
defaults: null
siteId: { }
methods: { }
priority: 2
creationDate: 1748444333
modificationDate: 1748444333
# backend/app/var/config/staticroutes/opendxp_ecommerce_product_detail.yaml
opendxp_static_routes:
definitions:
opendxp_ecommerce_product_detail:
name: opendxp_ecommerce_product_detail
pattern: '/(\b(?!admin\b)[a-zA-Z0-9-_]+)\/product\/(.*?)\~p([0-9]+)$/'
reverse: /%%_locale/product/%%name-p%product
controller: App\Controller\HeadlessController::nullAction
variables: '_locale,name,product'
defaults: null
siteId: { }
methods: { }
priority: 2
creationDate: 1748444333
modificationDate: 1748444333

Validation

All entity and form validation are bounded to group opendxp_ecommerce_api. If you need to add more granular validation, add your definition to config/validator/.

Copy all files from headless-ecommerce-bundle/config/validator/*.yaml.example to your app config/validator/ and remove the .example suffix.

Messenger

bin/console messenger:consume opendxp_ecommerce_notification opendxp_ecommerce_index --time-limit=300

This bundles ships some default definitions for category / product lists

# packages/dynamic_search.yaml
dynamic_search:
context:
default:
data_provider:
options:
always:
# add ecommerce objects
object_class_names:
- EcommerceCategory
- EcommerceProduct

services:
_defaults:
autowire: true
autoconfigure: true
public: false

# Create Document Definitions
App\DynamicSearch\Definition\Document\EcommerceProductDefinition: ~ # you may want to this class from OpenDxp\Bundle\HeadlessEcommerceBundle\DynamicSearch\Definition\Document\ProductDefinition
App\DynamicSearch\Definition\Document\EcommerceCategoryDefinition: ~ # you may want to this class from OpenDxp\Bundle\HeadlessEcommerceBundle\DynamicSearch\Definition\Document\CategoryDefinition

API Describer

Route Document Describer

nelmio_api_doc:
documentation:
components:
schemas:
# should already be defined in your project!
RouteDocumentAttributes:
items:
oneOf:
- $ref: '#/components/schemas/EcommerceAttribute' # <-- add this one
# [...]

Order Completion Validator

TBD


Extend Order Completion Form

Like any other form, you're able to extend the OpenDxp\Bundle\HeadlessEcommerceBundle\Form\Type\OrderMetaDataType by using a form extension service.

Still, there are two things you need to know:

  • You're not able to fetch the order object via $form->getData (because of security reasons) but will return the submitted metadata as plain array. The order object is available in form options order.
  • You need to take care about the mapping by yourself! Create a form event listener and populate the order via FormEvent::PRE_SUBMIT event for example.

Storage Lists

Storage Lists will help you to generate simple lists like wishlist / compare list easily

Configuration

opendxp_headless_ecommerce:
storage_list:

# Wishlist already exists in ecommerce bundle, so we can use the default storage list config
wishlist:
use_ecommerce_default_storage_list_config: true

# Comparelist does not exist in ecommerce bundle, so we have to define the models
# Everything else will be handled by ecommerce headless bundle
comparelist:
api_path_name: compare-list
storage_list_model: OpenDxp\Model\DataObject\EcommerceCompareList
storage_list_item_model: OpenDxp\Model\DataObject\EcommerceCompareListItem
# disable_caching: false / enable and set to true, if you want to disable opendxp object caching for list and list_item
# paths: define storage path for data objects
paths:
list: ecommerce/comparelist
item: items

Models

storage_list_model
  • needs to extend from OpenDxp\Bundle\HeadlessEcommerceBundle\StorageList\Model\StorageList class
  • required fields:
  • token [input]
  • items [ecommerceRelations]
  • customer [ecommerceRelation]
  • store [ecommerceStore]
storage_list_item_model
  • needs to extend from OpenDxp\Bundle\HeadlessEcommerceBundle\StorageList\Model\StorageListItem class
  • required fields:
    • product [ecommerceRelation] (Stack: opendxp_ecommerce.product)
    • quantity [numeric]
    • storageList [ecommerceRelation] (Stack: opendxp_ecommerce.[YOUR_STORAGE_LIST_NAME])

Add To Storage List DTO

If you need to use another AddToListDTO:

opendxp_headless_ecommerce:
storage_list:
comparelist:
add_to_storage_list_dto: App\DTO\YourAddToStorageListDtoClass

Expiration

If you want to enable the expiration service, add this to your storage_list_config

opendxp_headless_ecommerce:
storage_list:
comparelist:
expiration:
enabled: true
params:
days: 20
anonymous: true
customer: true

Storage Form Extension

services:
App\Form\Extension\AddToCompareListFormExtension:
tags:
- { name: form.type_extension, extended_type: OpenDxp\Bundle\HeadlessEcommerceBundle\StorageList\Form\AddToStorageListType }
<?php

namespace App\Form\Extension;

class AddToCompareListFormExtension extends AbstractTypeExtension
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
if ($options['storage_list_name'] === 'comparelist') {
$builder->add('myAdditionalFormField', TextType::class);
}
}

public static function getExtendedTypes(): iterable
{
return [AddToStorageListType::class];
}
}