Symfony2细枝移动模板回退

Symfony2细枝移动模板回退,symfony,mobile,twig,fallback,Symfony,Mobile,Twig,Fallback,我需要一个简单的方法来回退默认模板,如果没有移动版本存在 使用一些正则表达式,我可以识别移动平台,并希望使用以下模式呈现模板: <template_name>.mobile.html.twig .mobile.html.twig 但如果此模板不存在,我希望它自动回退到: <template_name>.html.twig .html.twig 它总是存在的 我尝试了这篇文章中几乎所有的答案: 但是没有成功。不幸的是,没有引用版本号 目前,我正在尝试复制和修改默认的

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

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

<template_name>.mobile.html.twig
.mobile.html.twig
但如果此模板不存在,我希望它自动回退到:

<template_name>.html.twig
.html.twig
它总是存在的

我尝试了这篇文章中几乎所有的答案: 但是没有成功。不幸的是,没有引用版本号

目前,我正在尝试复制和修改默认的细枝加载程序

顺便说一句,我想通过这种方式实现的是,只需添加一个同名模板并添加一个.mobile,就可以为移动设备部署不同的模板

更新:

这也是一个很好的方法。它修改请求对象的format属性,当您不使用渲染函数(或注释)在控制器中指定模板,而只是返回数组时,该属性会影响自动猜测模板

结果模板名称:

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

view/.

您不能检查模板以前是否存在吗

if ( $this->get('templating')->exists('<templatename>.html.twig') ) {
    //  return  this->render(yourtemplate)
} else {
    // return your default template
}
有了它,您可以:

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

通过利用Symfony2中的bundle继承属性,您可以轻松做到这一点

  • 创建一个包含桌面模板的捆绑包(AcmeDemoDesktopBundle)
  • 创建一个包含移动模板的捆绑包(AcmeDemobileBundle),并将父项标记为AcmeDemoDesktopBundle
然后,当您呈现一个模板时,只需调用acmedemobilebundle::-如果该模板存在,它将被呈现,否则您将整齐地返回到桌面版本。不需要额外的代码、侦听器或任何明显不需要的东西


当然,这样做的缺点是您将模板从单个捆绑包中移出。

您描述的回退行为并不容易实现(我们发现了困难的方法…)。好消息是,我们需要与您要求的相同的设置,并最终为此使用。它允许您根据设备等拥有不同的“主题”。它将为您提供备用部分

例如:

呈现模板:

@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

编辑:因此,使用这种方法,您可以拥有默认模板,它将始终是最终的备用模板,并在需要时为移动设备提供一个特殊模板。

您可以创建一个服务来处理它,然后以与使用模板服务相同的方式使用它

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

服务(YAML)

阶级

然后你可以调用你的模板服务而不是当前的

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

您可以让侦听器捕获不存在的模板错误。您可以在控制器级别(我在这里会这样做)使用不同的模板返回响应,或者重定向到仅限移动的url,甚至使用一些巧妙的变量或JS在模板上执行。您甚至可以在路由级别实现它。您可以定义自定义加载程序服务。可能性是无穷的:)是的,这将工作,但我正在寻找一种自动的方式来检查控制器以外的这一点。我试图覆盖细枝加载器,但有几种不同的方法都失败了,有关这方面的文档也不是很详细。我认为目前为止最好的解决方案是,也许我应该为此创建一个服务。好主意,但我看不到只有当设备是移动设备时才使用它的方法。此外,也没有办法访问非移动模板(如果存在移动版本)如果你想显示整个页面。@MarkusKottländer-问题表明你已经有了它,那么这只是一种巧妙的后退方式,而不是尝试使用不同的模板名称。@Qoop-这假设已经有了移动交换机,并且你只需要移动模板,但这是很好的一点。这是我想到的方式。谢谢!好吧……当我尝试你的解决方案时,我有点不满意。我真的很想在控制器中仅返回数组时获得基于控制器和动作名称的自动猜测模板。但我认为这种方式现在还可以。你是指在对模板使用注释时吗?是的,我刚刚遇到了另一个er问题。
控制器必须返回响应(…给定
TemplatingProvider的呈现函数似乎不返回响应对象,而是返回计划html文本,尽管它返回本机呈现函数的返回值。知道吗?好吧……呈现函数只应返回html。只有aof controlle内的快捷方式$this->renderr将其包装成响应。
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());