Symfony 2 load different template depending on user agent properties

后端 未结 8 1367
时光取名叫无心
时光取名叫无心 2020-12-02 17:28

Is it possible (and how) to

  • determine if a user is using a mobile device
  • force symfony 2 to load different template in that case
  • <
相关标签:
8条回答
  • 2020-12-02 17:47

    I think is nothing to do with symfony. Templates are for the VIEW. You may achieve this by using different CSS for the same template to get different layout (template). I am using jQuery and CSS to handle different devices. You may want to look at some source code of the UI from http://themeforest.net/; specifically this template. This is one handles different device.

    0 讨论(0)
  • 2020-12-02 17:47

    Alternative: https://github.com/suncat2000/MobileDetectBundle

    I found it quite good compared to https://github.com/kbond/ZenstruckMobileBundle and https://github.com/liip/LiipThemeBundle

    0 讨论(0)
  • 2020-12-02 17:48

    Well, you can use LiipThemeBundle.

    0 讨论(0)
  • 2020-12-02 17:49

    Ok, so I don't have a full solution but a little more than where to look for one :)

    You can specify loaders (services) for templating item in 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:         ~
    

    Then define the mentioned loader service:

    services:
        moby.loader:
            class: Acme\AppBundle\Twig\Loader\MobyFilesystemLoader
            arguments:    ["@templating.locator", "@service_container"]
    

    After that define your loader service class:

    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;
           }
     }
    

    As you can see this isn't the full solution, but I hope that this, at least, points you to the right direction.

    EDIT: Just found out that there is a bundle with mobile detection capabilities, with custom twig engine that renders template file depending on a device that sent request ZenstruckMobileBundle, although I never used it so... :)

    0 讨论(0)
  • 2020-12-02 17:50

    From my experiences, you can but by specifying a format in the first place - check these docs, they may be able to assist you

    0 讨论(0)
  • 2020-12-02 17:54

    You can utilize kernel.view event listener. This event comes to action when controller returns no response, only data. You can set reponse according to user agent property. For example

    In your controller,

    public function indexAction()
    {
        $data = ... //data prepared for view
        $data['template_name'] = "AcmeBlogBundle:Blog:index";
    
        return $data;
    }
    

    And the in your kernel.view event listener,

    <?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);
        }
    }
    

    Service definition,

    your_view_listener.listener:
        class: FQCN\Of\Listener\Class
        arguments:    [@templating]
        tags:
            - { name: kernel.event_listener, event: kernel.view, method: onKernelView }
    
    0 讨论(0)
提交回复
热议问题