How to create a sales channel context in Shopware 6
What can you do, when you need a sales channel context in some place in your code and it is not available there? Well that’s easy – you create it! And this article will show you how.
The requirements
First of all, we need to make sure, that we have all the requirements. For generating a new sales channel context in Shopware 6, we absolutely need to know the ID of the sales channel. Sales channel context is always valid for exactly one sales channel, so this is quite logical.
I also highly recommend having a language ID ready for sales channel context creation, especially for multi-language stores. Sure, we can create a sales channel context without one, but the system will then fall back to default. That might yield unexpected results later – for example, if we use the context, while retrieving data from repositories.
The last requirement is the SalesChannelContextFactory class, that will take care of the sales channel context generation process for us. You can inject it into your target class, just like any other service.
The availability of the sales channel ID and its language ID in Shopware 6 depends on where in the code we currently are. For example, if you had the SalesChannelEntity available in your custom method, you could extract these IDs quite easily like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?php namespace SomePlugin; use Shopware\Core\System\SalesChannel\SalesChannelEntity; class SomeClass { public function someFunction (SalesChannelEntity $salesChannelEntity) { $salesChannelId = $salesChannelEntity->getId(); $languageId = $salesChannelEntity->getLanguageId(); } } |
In general, you can always get the IDs from the Shopware 6 database, using repository. You can safely use the default context here. The following example shows, how to extract sales channel ID and language ID from the sales channel repository. It goes through all of the sales channels. In real life, you would set your custom criteria to filter exactly the one sales channel you want. If you are not sure, how to do that, you may read my little tutorial on Shopware 6 repositories and their filtering criteria.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
<?php namespace SomePlugin; use Shopware\Core\Framework\Context; use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria; use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\ContainsFilter; use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter; use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface; class SomeClass { private $salesChannelRepository; public function __construct( EntityRepositoryInterface $salesChannelRepository ) { $this->salesChannelRepository = $salesChannelRepository; } public function someFunction () { $data = $this->salesChannelRepository->search( (new Criteria()), Context::createDefaultContext() )->getElements(); foreach ($data as $item) { $salesChannelId = $item->getId(); $languageId = $item->getLanguageId(); } } } |
For completeness, here is also how the services.xml file should look like:
1 2 3 4 5 6 7 8 9 10 11 12 |
<?xml version="1.0" ?> <container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> <services> <service id="SomePlugin\SomeClass"> <argument type="service" id="sales_channel.repository"/> </service> </services> </container> |
The code for making a new sales channel context
Now, that we have the target sales channel ID and its language ID, we can finally create a new sales channel context, using the SalesChannelContextFactory class from the Shopware 6 core. A slightly different approach is needed to make things work, based on the Shopware version, that we are using, otherwise we might end up with an exception:
The main difference is, what service we need to inject. If you get an error message like “must be an instance of Shopware\Core\System\SalesChannel\Context\SalesChannelContextFactory, instance of Shopware\Core\System\SalesChannel\Context\CachedSalesChannelContextFactory given“, please check your Shopware version and inject the appropriate service. That is SalesChannelContextFactory for Shopware 6.3 and AbstractSalesChannelContextFactory for Shopware 6.4.
The services.xml file looks the same in both of these cases:
1 2 3 4 5 6 7 8 9 10 11 12 |
<?xml version="1.0" ?> <container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> <services> <service id="SomePlugin\SomeClass"> <argument type="service" id="Shopware\Core\System\SalesChannel\Context\SalesChannelContextFactory" /> </service> </services> </container> |
Note: Alternatively, you can also inject CachedSalesChannelContextFactory in version 6.4, but in that case, you would also have to change SalesChannelContextFactory to CachedSalesChannelContextFactory in the services.xml file.
Sales channel context factory in Shopware 6.3 or lower
The following code shows, how exactly we can inject the sales channel context factory to our class in Shopware version 6.3 or lower:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<?php namespace SomePlugin; use Shopware\Core\System\SalesChannel\Context\SalesChannelContextFactory; use Shopware\Core\System\SalesChannel\Context\SalesChannelContextService; class SomeClass { private $salesChannelContextFactory; public function __construct( SalesChannelContextFactory $salesChannelContextFactory ) { $this->salesChannelContextFactory = $salesChannelContextFactory; } public function createSalesChannelContext (string $salesChannelId, string $languageId) { return $this->salesChannelContextFactory->create('', $salesChannelId, [SalesChannelContextService::LANGUAGE_ID => $languageId]); } } |
Sales channel context factory in Shopware 6.4 and higher
And here is the code for injecting the sales channel context factory, that works in Shopware version 6.4 and higher:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<?php namespace SomePlugin; use Shopware\Core\System\SalesChannel\Context\AbstractSalesChannelContextFactory; use Shopware\Core\System\SalesChannel\Context\SalesChannelContextService; class SomeClass { private $salesChannelContextFactory; public function __construct( AbstractSalesChannelContextFactory $salesChannelContextFactory ) { $this->salesChannelContextFactory = $salesChannelContextFactory; } public function createSalesChannelContext (string $salesChannelId, string $languageId) { return $this->salesChannelContextFactory->create('', $salesChannelId, [SalesChannelContextService::LANGUAGE_ID => $languageId]); } } |
And that is it! Regardless of the Shopware version, that you use, you have a brand new sales channel context at your disposal now. ๐
I have updated this article with the information about the different approach in Shopware version 6.3 and 6.4. Please let me know, if you encounter some other incompatibilities in the future, so that I can update the article again.
Thanks Jan for the update, gave me the right hint ๐
Thanks Jan!
You saved my life ๐