Symfony2枝条移动模板后备

时间:2013-12-06 11:47:50

标签: symfony mobile twig fallback

如果不存在移动版本,我需要一种简单的方法来回退默认模板。

使用一些正则表达式,我会识别移动平台,并希望使用以下模式渲染模板:

<template_name>.mobile.html.twig

但是如果这个模板不存在,我希望它能自动回退:

<template_name>.html.twig

始终存在。

我试过这篇文章的几乎所有答案: Symfony 2 load different template depending on user agent properties 但没有成功。不幸的是,没有引用版本号。

目前我正在尝试复制和修改默认的树枝加载器。

顺便说一下,......我想要实现的目标是通过添加同名模板并添加.mobile为移动设备部署不同的模板。

更新

http://www.99bugs.com/handling-mobile-template-switching-in-symfony2/ 这个也是一个很好的方法。当你没有在控制器中使用渲染函数(或注释)指定模板但只返回数组时,它会修改请求对象的格式属性,这会影响自动模板猜测。

结果模板名称:

view/<controller>/<action>.<request format>.<engine>

因此,您可以根据设备检测将请求格式从html切换到mobile.html。 这样做的缺点是每个模板都需要一个mobile.html挂件(如果不需要,可以包含非移动版本)。

更新

除了使用自定义模板提供程序外,还有hook into the kernel.view event的可能性。

4 个答案:

答案 0 :(得分:2)

你可以创建一个服务来处理它,然后像你做模板服务那样使用它。

创建一个注入模板和请求服务的服务..

服务(YAML)

acme.templating: 
    class: Acme\AcmeBundle\Templating\TemplatingProvider
    scope: request
    arguments:
        - @templating
        - @request // I assume you use request in your platform decision logic,
                   // otherwise you don't needs this or the scope part
        - 'html' 

class TemplatingProvider
{
    private $fallback;
    private $platform;
    ... __construct($templating, $request, $fallback) etc

    private function setPlatform() ... Your platform decision logic

    private function getPlatform()
    {
        if (null === $this->platform) {
            $this->setPlatform();
        }

        return $this->platform;
    }

    private function getTemplateName($name, $platform)
    {
        if ($platform === 'html') {
            return $name;
        }

        $template = explode('.', $name);

        $template = array_merge(
            array_slice($template, 0, -2),
            array($platform),
            array_slice($template, -2)
        );

        return implode('.', $template);
    }

    public function renderResponse($name, array $parameters = array())
    {
        $newname = $this->getTemplateName($name, $this->getPlatform());

        if ($this->templating->exists($newname)) {
            return $this->templating->render($newname);
        }

        return $this->templating->renderResponse($this->getTemplateName(
                                                $name, $this->fallback));
    }

然后你可以调用你的模板服务而不是现在的服务..

return $this->container->get('acme.templating')
                          ->renderResponse('<template_name>.html.twig', array());

答案 1 :(得分:1)

你不能检查模板是否存在吗?

if ( $this->get('templating')->exists('<templatename>.html.twig') ) {
    //  return  this->render(yourtemplate)
} else {
    // return your default template
}

或:

您可以创建一个通用方法,在根控制器中插入,如:

public function renderMobile($templateName, $params)
{
    $templateShortName = explode('.html.twig', $templateName)[0];
    $mobileName = $templateShortName.'.mobile.html.twig';
    if ( $this->get('templating')->exists($mobileName) ) {

        return $this->renderView($mobileName, $params);
    } else {
        return $this->renderView($templateName, $params)
    }
}

你可以这样做:

return $this->renderMobile('yourtemplate', [yourparams]);

答案 2 :(得分:0)

您可以通过利用Symfony2 http://symfony.com/doc/current/cookbook/bundles/inheritance.html中的包继承属性轻松完成此操作

  • 创建一个包含桌面模板的包(AcmeDemoDesktopBundle)
  • 创建一个包含移动模板的包(AcmeDemoMobileBundle)并将父标记为AcmeDemoDesktopBundle

然后当您渲染模板时,只需调用AcmeDemoMobileBundle :: - 如果模板存在,它将被渲染,否则您将整齐地回退到桌面版本。没有额外的代码,听众或任何不明显的要求。

当然,这样做的缺点是您可以将模板移出各个捆绑包。

答案 3 :(得分:0)

您描述的后备行为并不容易实现(我们发现了困难的方法......)。好消息是我们想要您提出的相同设置,并最终使用LiipThemeBundle来达到此目的。它允许您基于例如设备具有不同的“主题”。它会为你做后备部分。

例如:

渲染模板: @BundleName/Resources/template.html.twig

将按顺序渲染和回退:

  • app/Resources/themes/phone/BundleName/template.html.twig
  • app/Resources/BundleName/views/template.html.twig
  • src/BundleName/Resources/themes/phone/template.html.twig
  • src/BundleName/Resources/views/template.html.twig

编辑:因此,通过这种方法,您可以拥有默认模板,这些模板始终是最终的后备模式,并为您需要的移动设备提供特殊模板。