The E-Commerce Framework is implemented as semantic bundle configuration which means that you can configure the framework
in any of the loaded config files (e.g.
adding configuration to the
The configuration is built upon the Symfony Config Component and defines a well-known configuration tree which is validated against a defined configuration structure. While configuring the framework you'll get instant feedback on configuration errors. As Pimcore defines a standard configuration for the E-Commerce Framework, your custom configuration will be merged into the standard configuration. You can dump the final (merged, validated and normalized) configuration at any time with the following command:
$ bin/console debug:config pimcore_ecommerce_framework
A reference of available configuration entries can be found on PimcoreEcommerceFrameworkBundle Configuration Reference.
As the E-Commerce Framework makes heavy use of Symfony service definitions and you'll need to reference IDs of custom services in the configuration it's advised that you are comfortable to work with Symfony's Service Container.
Tenant support and
As certain components of the E-Commerce Framework support different tenants, Pimcore adds a way to specify settings
which are common to all tenants in a special tenant named
_defaults. If such a tenant exists, its values will be merged
into all other tenants and the
_defaults tenant will be removed afterwards. The logic described below applies to all
components supporting tenants.
As example, a simple
cart_manager configuration section which defines a
default and a
pimcore_ecommerce_framework: cart_manager: tenants: # _defaults will be automatically merged into every tenant and removed afterwards # the result will be a default and a noShipping _defaults: cart: factory_id: CartFactoryId price_calculator: factory_id: PriceCalculatorFactoryId factory_options: foo: bar default: price_calculator: factory_options: baz: 1234 noShipping: price_calculator: factory_options: baz: 4321
In addition to the
_defaults tenant, you can define additional tenants starting with
_defaults to make use
of YAML inheritance.
pimcore_ecommerce_framework: cart_manager: tenants: _defaults_foo: price_calculator: factory_options: &defaults_foo_options # define an anchor class: MyCommonCalculatorClass default: price_calculator: factory_options: <<: *defaults_foo_options # import anchor anotherOne: price_calculator: factory_options: <<: *defaults_foo_options # import anchor
Of course you can still use the PHP config file format by importing a PHP config file from your
config.yaml to be
completely free how to merge common configuration entries.
Service IDs and tenant specifics
When configuring tenant specific services, there are multiple configuration entries demanding a service ID as configuration value. This means, the system expects the configured value to be available as service definition on the container. You can read through the service definitions defined in PimcoreEcommerceFrameworkBundle to get an insight of default e-commerce services.
As an example let's take a look at a price system configuration:
# when loading the "default" price system, use a service named "App\Ecommerce\PriceSystem\CustomPriceSystem" pimcore_ecommerce_framework: price_systems: default: # price system defined and configured as container service id: App\Ecommerce\PriceSystem\CustomPriceSystem
The configuration above expects something like this configured as service:
services: App\Ecommerce\PriceSystem\CustomPriceSystem: arguments: - 'foo'
The "default" price system is just an alias to your existing service and when loading that price system, your service will
be directly loaded. Getting the "default" price system from the ecommerce framework factory will result in the same instance
App\Ecommerce\PriceSystem\CustomPriceSystem directly from the container.
Service IDs in tenant context
Now let's take a look at another example handling tenants:
pimcore_ecommerce_framework: order_manager: tenants: default: order_manager_id: Pimcore\Bundle\EcommerceFrameworkBundle\OrderManager\OrderManager options: parent_order_folder: /orders/default/%%Y/%%m/%%d b2b: order_manager_id: Pimcore\Bundle\EcommerceFrameworkBundle\OrderManager\OrderManager options: parent_order_folder: /orders/b2b/%%Y/%%m/%%d
As you can see we define 2 tenants
b2b with the same order manager ID but with different options for
each tenant. In this case it's not possible to just alias the default or the b2b order manager to the given service ID as
we need multiple order manager instances based on this service definition. In this case the framework takes the configured
service ID as template to configure 2 independent child services by utilizing the configured service id as parent service.
This means, that when you request the
Pimcore\Bundle\EcommerceFrameworkBundle\OrderManager\OrderManager service from the
container, it would be neither the default nor the b2b tenant. In fact, getting that service directly wouldn't work anyways
as it is missing dependencies. If you take a look at the service definition
you can see that the definition is missing the
OrderAgentFactoryInterface argument which will be resolved and set for each
tenant specific order manager.
In short, when configuring multiple tenant specific service to the same service id the framework will:
- create a new child definition from the configured service
- set tenant specific arguments (as the options above) to the tenant specific child service
- register the child service under a another ID which can be resolved by the factory
To keep your services clean and give the service container more optimization (and performance) possibilities you should
define your parent services as
private (see order manager definition in the linked config above) as this will result
in the parent definition being removed from the compiled container.
This child definition pattern applies to nearly all service IDs configured inside tenants with the exception of reusable services (e.g. getters and interpreters in the product index configuration) which do not have an internal state and therefore can be reused throughout multiple tenants.