Symfony 2 загружает разные шаблоны в зависимости от свойств агента пользователя
Возможно ли (и как) на
- определить, использует ли пользователь мобильное устройство
- заставить symfony 2 загружать другой шаблон в этом случае
- (и отменить шаблон html по умолчанию)
Какой идентификатор должен делать, это загрузить различные шаблоны без изменения какого-либо контроллера.
UPDATE
Здесь не была часть обнаружения, это действительно не имеет никакого отношения к symfony. Это можно сделать (загрузить другой шаблон) на уровне контроллера:
public function indexAction()
{
$format = $this->isMobile() ? 'mob' : 'html';
return $this->render('AcmeBlogBundle:Blog:index.'.$format.'.twig');
}
Но можно ли это сделать глобально? Как сервис или что-то, что выполняется перед каждым запросом, и вносить изменения в правила шаблонов.
Ответы
Ответ 1
Хорошо, поэтому у меня нет полного решения, но немного больше, чем искать его:)
Вы можете указать загрузчики (сервисы) для шаблонов в 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;
}
}
Как вы можете видеть, это не полное решение, но я надеюсь, что это, по крайней мере, указывает на правильное направление.
EDIT: только что узнал, что есть набор с возможностями обнаружения мобильных устройств, с настраиваемым движком ветки, который отображает файл шаблона в зависимости от устройства, которое отправил запрос
ZenstruckMobileBundle, хотя я никогда не использовал его так...:)
Ответ 2
Хорошо, вы можете использовать LiipThemeBundle.
Ответ 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 }
Ответ 4
Вот что помогло в 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
}
}
Ответ 5
Я бы предположил, что это не лучше всего обрабатывается контроллером, а средствами CSS-запросов и служит отдельной таблицей стилей для разных классов устройств на основе результатов этого мультимедийного запроса CSS.
Хорошее введение здесь:
http://www.adobe.com/devnet/dreamweaver/articles/introducing-media-queries.html
и я бы очень подробно прочитал http://www.abookapart.com/products/responsive-web-design. Некоторое мышление было сделано после того, как книга была опубликована, но она заставит вас идти в правильном направлении.
Ответ 6
Из моего опыта вы можете, но указав формат в первую очередь - проверьте эти docs, они могут помочь вам
Ответ 7
Я думаю, не имеет ничего общего с symfony. Шаблоны предназначены для просмотра. Вы можете достичь этого, используя другой CSS для одного и того же шаблона, чтобы получить разный макет (шаблон). Я использую jQuery и CSS для обработки различных устройств. Вы можете посмотреть на некоторый исходный код пользовательского интерфейса из http://themeforest.net/; в частности, это template. Это одна ручка для другого устройства.
Ответ 8
Альтернатива: https://github.com/suncat2000/MobileDetectBundle
Я нашел это неплохо по сравнению с https://github.com/kbond/ZenstruckMobileBundle и https://github.com/liip/LiipThemeBundle