对于我的项目,我需要针对不同设备的多个主题设计,但现在在一个频道中,只能选择一个主题。
例如, 如果我有频道"日本"在日本销售,我想为每个设备多个主题:移动,平板电脑和PC。因此,用户将看到主题取决于他们的设备。
我需要一些关于使用单一渠道为不同设备创建多个主题/风格的想法。
那么,有什么想法吗?
答案 0 :(得分:2)
好的,负责当前主题的服务是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
服务(a.k.a。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
作为其主题名称)。
我希望这是一个足够明确的指令来帮助您前进,因为注入可以检测到正确设备名称的服务并不是很难做到,但是如果您无法弄清楚,请告诉我,我将通过实施这一点来扩展它。