I come from Magento and I now use Sylius to modernize things a bit and have access to a less xml oriented platform because I find it really painful in 2022...
Unfortunately I did not find anything in Sylius regarding the management of prices according to the client currently logged.
So I want to use groups and channels: I added a channel relation to a user group to be able to use a channel according to the logged in user.
/**
* @ORM\Entity
* @ORM\Table(name="sylius_customer_group")
*/
class CustomerGroup extends BaseCustomerGroup
{
/**
* @ORM\ManyToOne(targetEntity=Channel::class)
*/
private $channel;
public function getChannel(): ?Channel
{
return $this->channel;
}
public function setChannel(?Channel $channel): self
{
$this->channel = $channel;
return $this;
}
}
Here is what I am trying to do with a service
services:
ChangingContextWithCustomerGroup:
class: App\Context\RequestQueryChannelContext
arguments:
- '@sylius.repository.channel'
- '@request_stack'
- '@sylius.context.customer'
tags:
- { name: sylius.context.channel, priority: 150 }
// src/Context/RequestQueryChannelContext.php
public function getChannel(): ChannelInterface
{
$request = $this->requestStack->getMainRequest();
if (!$request) {
throw new ChannelNotFoundException('Request Not Found!');
}
$customer = $this->customerContext->getCustomer();
if (!$customer instanceof Customer) {
throw new ChannelNotFoundException('Customer Not Found!');
}
$group = $customer->getGroup();
if (!$group instanceof CustomerGroup) {
throw new ChannelNotFoundException('Group Not Found!');
}
$channel = $group->getChannel();
if (!$channel instanceof ChannelInterface) {
throw new ChannelNotFoundException('Channel Not Found!');
}
return $channel;
}
My problem is that I can't get the customer on the mainRequest. It is null, so I cant have the customer => group => channel.
It works very well when I force the channel like this:
public function getChannel(): ChannelInterface
{
// ...
return $this->channelRepository->findOneByCode('fooBar');
}
so my system doesn't work. Is there a better solution?
thanks
The problem here is that the Channel context is called from the Sylius\Bundle\ShopBundle\EventListener\NonChannelLocaleListener
which has priority 10 on the kernel.request
event. In the channel context you want to use the customer context class, which in turn uses the TokenStorage
to retrieve the user information. The token however is not yet populated in the token storage at that point, because that happens in the firewall listener ( Symfony\Bundle\SecurityBundle\Debug\TraceableFirewallListener
in dev environments), which has priority 8.
The solution I found is to lower the priority of the NonChannelLocaleListener
to 7. That will make sure that the token is available and that the customer context can be used to retrieve the customer/shop user information.
Lowering the priority of that listener can be done by overriding the service definition in config/services.yaml
:
services:
...
sylius.listener.non_channel_request_locale:
class: Sylius\Bundle\ShopBundle\EventListener\NonChannelLocaleListener
arguments:
- '@router'
- '@sylius.locale_provider'
- '@security.firewall.map'
- ['%sylius_shop.firewall_context_name%']
tags:
- { name: kernel.event_listener, event: kernel.request, method: restrictRequestLocale, priority: 7 }
Please note that this is on Sylius 1.10, so it might be possible that on other Sylius versions the priority of these listeners are slightly different. In that case, just use the bin/console debug:event-dispatcher
command to figure out what the right priority should be.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.