Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symfony 2 load different template depending on user agent properties

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
  • (and fall back the default html template)

What id like to do is, to load different templates without modifying any controller.

UPDATE

It wasn't the detection part the real issue here, it's really nothing to do with symfony. It can be done (load different template) on a controller level:

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

But can it be done globally? Like a service, or something that execute before every request, and make changes in the templating rules.

like image 311
user1063963 Avatar asked Nov 24 '11 13:11

user1063963


2 Answers

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... :)

like image 63
Marko Jovanović Avatar answered Oct 22 '22 02:10

Marko Jovanović


Well, you can use LiipThemeBundle.

like image 6
Henrik Bjørnskov Avatar answered Oct 22 '22 02:10

Henrik Bjørnskov