Symfony 2 загружает разные шаблоны в зависимости от свойств агента пользователя

Возможно ли (и как)

  • определить, использует ли пользователь мобильное устройство
  • заставить symfony 2 загружать другой шаблон в этом случае
  • (и отказаться от шаблона html по умолчанию)

Какой id нравится делать, чтобы загрузить различные шаблоны без изменения какого-либо контроллера.

ОБНОВИТЬ

Здесь не проблема обнаружения, это не имеет никакого отношения к symfony. Это можно сделать (загрузить другой шаблон) на уровне контроллера:

public function indexAction() { $format = $this->isMobile() ? 'mob' : 'html'; return $this->render('AcmeBlogBundle:Blog:index.'.$format.'.twig'); } 

Но можно ли это сделать глобально? Как сервис или что-то, что выполняется перед каждым запросом, и вносить изменения в правила шаблонов.

Хорошо, поэтому у меня нет полного решения, но немного больше, чем искать один 🙂

Вы можете указать загрузчики (сервисы) для шаблонирования элемента в 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 , хотя я никогда не использовал его так … 🙂

Ну, вы можете использовать LiipThemeBundle .

Вы можете использовать kernel.view событий 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 } 

Вот что сделал трюк для меня в 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 } } 

Я бы предположил, что это не лучше всего обрабатывается контроллером, а средствами CSS-запросов и служит отдельной таблицей стилей для разных классов устройств на основе результатов этого медиа-запроса CSS. Хорошее введение здесь: http://www.adobe.com/devnet/dreamweaver/articles/introducing-media-queries.html

и я бы очень пробовал читать http://www.abookapart.com/products/responsive-web-design . Некоторое мышление было сделано после того, как книга была опубликована, но она заставит вас идти в правильном направлении.

Из моего опыта вы можете, но указав формат в первую очередь – проверьте эти документы , они могут помочь вам

Я думаю, не имеет ничего общего с symfony. Шаблоны предназначены для просмотра. Вы можете достичь этого, используя другой CSS для одного и того же шаблона, чтобы получить разный макет (шаблон). Я использую jQuery и CSS для обработки различных устройств. Вы можете посмотреть на некоторый исходный код пользовательского интерфейса от http://themeforest.net/ ; в частности, этот шаблон . Это одна ручка для другого устройства.

Альтернатива: https://github.com/suncat2000/MobileDetectBundle

Я нашел это довольно хорошим по сравнению с https://github.com/kbond/ZenstruckMobileBundle и https://github.com/liip/LiipThemeBundle