Symfony2 twig 移动模板后备

问题描述 投票:0回答:4

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

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

<template_name>.mobile.html.twig

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

<template_name>.html.twig

永远存在。

我几乎尝试了这篇文章中的所有答案: Symfony 2 根据用户代理属性加载不同的模板 但没有成功。不幸的是,没有引用版本号。

目前我正在尝试复制和修改默认的twig loader。

顺便说一句,我想通过此实现的是只需添加同名模板并添加 .mobile 即可为移动设备部署不同的模板。

更新:

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

生成的模板名称:

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

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

更新:

除了使用自定义模板提供程序之外,还可以挂钩 kernel.view 事件

php symfony mobile twig fallback
4个回答
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
投票

你不能检查一下模板之前是否存在吗?

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]);

0
投票

您可以通过利用 Symfony2 中的包继承属性轻松做到这一点http://symfony.com/doc/current/cookbook/bundles/inheritance.html

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

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

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


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

编辑:因此,通过这种方法,您可以拥有默认模板,该模板始终是最终的后备方案,并且在您需要的地方有一个针对移动设备的特殊模板。

© www.soinside.com 2019 - 2024. All rights reserved.