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

Можно ли (и как)

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

То, что я хотел бы сделать, это загружать различные шаблоны без изменения какого-либо контроллера.

ОБНОВЛЕНИЕ

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

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

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

Ответы [ 8 ]

23 голосов
/ 13 августа 2012

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

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

6 голосов
/ 15 августа 2012

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

3 голосов
/ 17 августа 2012

Вы можете использовать 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 }
2 голосов
/ 10 октября 2013

Вот что помогло мне в Symfony 2.0:

Переопределить службу twig.loader, чтобы мы могли установить наш пользовательский класс:

twig.loader:
    class: Acme\AppBundle\TwigLoader\MobileFilesystemLoader
    arguments:
        locator:  "@templating.locator"
        parser:   "@templating.name_parser"

И создать наш собственный класс, которыйпросто устанавливает формат «моб» ​​для шаблонов на случай, если клиент является мобильным устройством:

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
    }
 }
1 голос
/ 17 августа 2012

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

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

0 голосов
/ 24 октября 2012

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

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

0 голосов
/ 03 августа 2012

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

0 голосов
/ 30 ноября 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...