2016-05-17 42 views
1

對於我的項目,我需要針對不同設備的多個主題設計,但現在在一個頻道中,只能選擇一個主題。在Sylius的單個頻道上的多個主題的想法

例如, 如果我有在日本銷售的頻道「日本」,我想爲每個設備的多個主題:手機,平板電腦和PC。所以用戶會看到主題取決於他們的設備。

我需要一些關於使用單個通道爲不同設備創建多個主題/樣式的想法。

那麼,有什麼想法?

回答

2

好的,所以負責當前主題的服務是sylius.context.theme服務。如果您使用Sylius full stack,則將使用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)。

我希望這是一個足夠明確的指令,以幫助您順利進行,因爲注入可以檢測到適當設備名稱的服務並不難,我猜,但如果您無法弄清楚,請告訴我我也會通過實施這個來擴展它。