Is it possible (and how) to
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.
Alternative: https://github.com/suncat2000/MobileDetectBundle
I found it quite good compared to https://github.com/kbond/ZenstruckMobileBundle and https://github.com/liip/LiipThemeBundle
Well, you can use LiipThemeBundle.
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... :)
From my experiences, you can but by specifying a format in the first place - check these docs, they may be able to assist you
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 }