Хорошо, поэтому сервис, отвечающий за текущую тему, - это услуга sylius.context.theme
. Если вы используете полный стек Sylius, тогда будет использоваться ChannelBasedThemeContext
(см.: https://github.com/Sylius/SyliusCoreBundle/blob/master/Theme/ChannelBasedThemeContext.php). Как вы можете видеть в исходном коде, он просто находит тему, которую вы установили по свойству темы themeName
на текущем канале. Зная это, мы можем реализовать свои собственные путем внедрения ThemeContextInterface
. Потому что в вашем случае вы, вероятно, захотите вернуться к поведению по умолчанию, когда темы japan_mobile
не существует, мы собираемся украсить службу sylius.context.theme
вместо того, чтобы ее заменять!
Итак, давайте начнем с создания Acme\AppBundle\Theme\DeviceBasedThemeContext
:
namespace Acme\AppBundle\Theme\DeviceBasedThemeContext;
use Sylius\Bundle\ThemeBundle\Context\ThemeContextInterface;
use Sylius\Bundle\ThemeBundle\Repository\ThemeRepositoryInterface;
use Sylius\Component\Channel\Context\ChannelContextInterface;
use Sylius\Component\Channel\Context\ChannelNotFoundException;
use Sylius\Component\Core\Model\ChannelInterface;
final class DeviceBasedThemeContext implements ThemeContextInterface
{
/**
* @var ThemeContextInterface
*/
private $decoratedThemeContext;
/**
* @var ChannelContextInterface
*/
private $channelContext;
/**
* @var ThemeRepositoryInterface
*/
private $themeRepository;
/**
* @param ThemeContextInterface $decoratedThemeContext
* @param ChannelContextInterface $channelContext
* @param ThemeRepositoryInterface $themeRepository
*/
public function __construct(
ThemeContextInterface decoratedThemeContext,
ChannelContextInterface $channelContext,
ThemeRepositoryInterface $themeRepository
) {
$this->decoratedThemeContext = $decoratedThemeContext;
$this->channelContext = $channelContext;
$this->themeRepository = $themeRepository;
}
/**
* {@inheritdoc}
*/
public function getTheme()
{
try {
/** @var ChannelInterface $channel */
$channel = $this->channelContext->getChannel();
$deviceThemeName = $channel->getThemeName().’_’.$this->getDeviceName();
// try to find a device specific version of this theme, if so, it will use that one
if ($theme = $this->themeRepository->findOneByName($deviceThemeName) {
return $theme;
}
// fallback to use the default theme resolving logic
return $this->decoratedThemeContext->getTheme();
} catch (ChannelNotFoundException $exception) {
return null;
} catch (\Exception $exception) {
return null;
}
}
private function getDeviceName()
{
// here you should return the proper device name
return ‘mobile’;
}
}
Теперь, когда мы имеем контекст тема закончена, мы должны сделать контейнерный сервис признать это, мы делаем это, украшая существующий sylius.theme.context
службы (ака ChannelBasedThemeContext
).
Так что в вашем services.xml
добавить следующие услуги:
<service id="acme.context.theme.device_based" class="Acme\AppBundle\Theme\DeviceBasedThemeContext"
decorates=“sylius.theme.context”>
<argument type=“service” id=“acme.context.theme.device_based.inner”/>
<argument type=“service” id=“sylius.context.channel”/>
<argument type=“service” id=“sylius.repository.theme”/>
</service>
И вы сделали! Если вы очистите кеши, теперь нужно попробовать сначала загрузить japan_mobile
, если он не существует, он просто загрузит тему japan
(при условии, что текущий канал имеет japan
в качестве названия своей темы).
Я надеюсь, что это достаточно ясная инструкция, чтобы помочь вам двигаться, для инъекции службы, которая может обнаружить правильное имя устройства, не так сложно сделать, я думаю, но если вы не можете понять это, дайте мне знать и я продолжу это, реализуя это тоже.