如果不存在移动版本,我需要一种简单的方法来回退到默认模板。
通过一些正则表达式,我可以识别移动平台,并希望使用以下模式呈现模板:
<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 事件。
您可以创建一个服务来处理它,然后以与模板服务相同的方式使用它..
创建一个服务,并将模板和请求服务注入其中..
服务(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());
你不能检查一下模板之前是否存在吗?
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]);
您可以通过利用 Symfony2 中的包继承属性轻松做到这一点http://symfony.com/doc/current/cookbook/bundles/inheritance.html
然后,当您渲染模板时,只需调用 AcmeDemoMobileBundle:: - 如果模板存在,它将被渲染,否则您将整齐地回退到桌面版本。不需要额外的代码、监听器或任何不明显的东西。
当然,这样做的缺点是您将模板从各个捆绑包中移出。
您描述的后备行为并不容易实现(我们发现了困难的方法......)。好消息是我们想要与您要求的设置相同的设置,并最终使用 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
编辑:因此,通过这种方法,您可以拥有默认模板,该模板始终是最终的后备方案,并且在您需要的地方有一个针对移动设备的特殊模板。