是否可能(以及如何)
id喜欢做的是,在不修改任何控制器的情况下加载不同的模板。
更新
这不是检测部分真正的问题,它与symfony无关。它可以在控制器级别上完成(加载不同的模板):
public function indexAction()
{
$format = $this->isMobile() ? 'mob' : 'html';
return $this->render('AcmeBlogBundle:Blog:index.'.$format.'.twig');
}
但它可以在全球范围内完成吗?就像服务,或者在每个请求之前执行的事情,并在模板规则中进行更改。
答案 0 :(得分:23)
好的,所以我没有一个完整的解决方案,只是在哪里寻找一个:)
您可以在app / config / config.yml
中为模板项指定加载器(服务)framework:
esi: { enabled: true }
#translator: { fallback: %locale% }
secret: %secret%
router:
resource: "%kernel.root_dir%/config/routing.yml"
strict_requirements: %kernel.debug%
form: true
csrf_protection: true
validation: { enable_annotations: true }
templating:
engines:
- twig
loaders: [moby.loader]
default_locale: %locale%
trust_proxy_headers: false
session: ~
然后定义提到的加载器服务:
services:
moby.loader:
class: Acme\AppBundle\Twig\Loader\MobyFilesystemLoader
arguments: ["@templating.locator", "@service_container"]
之后定义您的加载器服务类:
namespace Acme\AppBundle\Twig\Loader;
use Symfony\Bundle\FrameworkBundle\Templating\Loader\FilesystemLoader;
use Symfony\Component\Templating\Storage\FileStorage;
class MobyFilesystemLoader extends FilesystemLoader
{
protected $container;
public function __construct($templatePathPatterns, $container)
{
parent::__construct($templatePathPatterns);
$this->container = $container;
}
public function load(\Symfony\Component\Templating\TemplateReferenceInterface $template)
{
// Here you can filter what you actually want to change from html
// to mob format
// ->get('controller') returns the name of a controller
// ->get('name') returns the name of the template
if($template->get('bundle') == 'AcmeAppBundle')
{
$request = $this->container->get('request');
$format = $this->isMobile($request) ? 'mob' : 'html';
$template->set('format', $format);
}
try {
$file = $this->locator->locate($template);
} catch (\InvalidArgumentException $e) {
return false;
}
return new FileStorage($file);
}
/**
* Implement your check to see if request is made from mobile platform
*/
private function isMobile($request)
{
return true;
}
}
正如您所看到的,这不是完整的解决方案,但我希望这至少可以指出您正确的方向。
编辑:刚发现有一个具有移动检测功能的捆绑包,自定义枝条引擎根据发送请求的设备呈现模板文件 ZenstruckMobileBundle,虽然我从未使用过它...... :)
答案 1 :(得分:6)
好吧,你可以使用LiipThemeBundle。
答案 2 :(得分:3)
您可以使用kernel.view
事件监听器。当控制器没有响应,只返回数据时,此事件开始动作。您可以根据用户代理属性设置响应。例如
在你的控制器中,
public function indexAction()
{
$data = ... //data prepared for view
$data['template_name'] = "AcmeBlogBundle:Blog:index";
return $data;
}
在您的kernel.view
事件监听器
<?php
namespace Your\Namespace;
use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Templating\EngineInterface;
Class ViewListener
{
/**
* @var EngineInterface
*/
private $templating;
public function __construct(EngineInterface $templating)
{
$this->templating = $templating;
}
public function onKernelView(GetResponseForControllerResultEvent $event)
{
$data = $event->getControllerResult(); //result returned by the controller
$templateName = $data['template_name'];
$format = $this->isMobile() ? 'mob' : 'html'; //isMobile() method may come from a injected service
$response = $this->templating->renderResponse($templateName . "." . $format . "twig", $data);
$event->setResponse($response);
}
}
服务定义,
your_view_listener.listener:
class: FQCN\Of\Listener\Class
arguments: [@templating]
tags:
- { name: kernel.event_listener, event: kernel.view, method: onKernelView }
答案 3 :(得分:2)
这就是Symfony 2.0中的诀窍:
覆盖twig.loader服务,以便我们设置自定义类:
twig.loader:
class: Acme\AppBundle\TwigLoader\MobileFilesystemLoader
arguments:
locator: "@templating.locator"
parser: "@templating.name_parser"
创建我们的自定义类,只需将“mob”格式设置为模板,以防客户端是移动设备:
namespace Acme\AppBundle\TwigLoader;
use Symfony\Bundle\TwigBundle\Loader\FilesystemLoader;
class MobileFilesystemLoader extends FilesystemLoader
{
public function findTemplate($template)
{
if ($this->isMobile()) {
$template->set('format', 'mob');
}
return parent::findTemplate($template);
}
private function isMobile()
{
//do whatever to detect it
}
}
答案 4 :(得分:1)
我建议这不是最好由控制器处理,而是由CSS媒体查询处理,并根据CSS媒体查询的结果为不同类别的设备提供单独的样式表。 这里有一个很好的介绍: http://www.adobe.com/devnet/dreamweaver/articles/introducing-media-queries.html
我会非常详细地阅读http://www.abookapart.com/products/responsive-web-design。自该书出版以来,已经做了一些思考,但它会让你朝着正确的方向前进。
答案 5 :(得分:0)
我认为与symfony无关。模板用于VIEW。您可以通过对同一模板使用不同的CSS来获得不同的布局(模板)。我使用jQuery和CSS来处理不同的设备。您可能希望从http://themeforest.net/查看UI的一些源代码;特别是template。这是一个处理不同的设备。
答案 6 :(得分:0)