Est-il possible (et comment) de
Ce que j’aime faire, c’est de charger différents modèles sans modifier aucun contrôleur.
METTRE À JOUR
Le vrai problème ici, ce n’était pas la détection, c’est vraiment rien à voir avec symfony. Cela peut être fait (charger un modèle différent) au niveau du contrôleur:
public function indexAction()
{
$format = $this->isMobile() ? 'mob' : 'html';
return $this->render('AcmeBlogBundle:Blog:index.'.$format.'.twig');
}
Mais cela peut-il être fait globalement? Comme un service, ou quelque chose qui s'exécute avant chaque requête et modifie les règles du modèle.
Ok, donc je n'ai pas de solution complète mais un peu plus que l'endroit où en chercher une :)
Vous pouvez spécifier des chargeurs (services) pour les éléments de gabarit dans 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: ~
Définissez ensuite le service de chargement mentionné:
services:
moby.loader:
class: Acme\AppBundle\Twig\Loader\MobyFilesystemLoader
arguments: ["@templating.locator", "@service_container"]
Après cela, définissez votre classe de service de chargeur:
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;
}
}
Comme vous pouvez le constater, cette solution n’est pas complète, mais j’espère que cela vous aidera au moins à aller dans la bonne direction.
EDIT: Je viens de découvrir qu’il existe un ensemble de fonctionnalités de détection mobile, avec un moteur de brindille personnalisé qui rend le fichier de modèle en fonction du périphérique qui a envoyé la demande ZenstruckMobileBundle , bien que je ne l’aie jamais utilisé alors ... :)
Eh bien, vous pouvez utiliser LiipThemeBundle .
Vous pouvez utiliser l'écouteur d'événements kernel.view
. Cet événement se déclenche lorsque le contrôleur ne renvoie aucune réponse, uniquement des données. Vous pouvez définir la réponse en fonction de la propriété de l'agent utilisateur. Par exemple
Dans votre contrôleur,
public function indexAction()
{
$data = ... //data prepared for view
$data['template_name'] = "AcmeBlogBundle:Blog:index";
return $data;
}
Et le dans votre écouteur d'événements 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);
}
}
Définition du service,
your_view_listener.listener:
class: FQCN\Of\Listener\Class
arguments: [@templating]
tags:
- { name: kernel.event_listener, event: kernel.view, method: onKernelView }
C’est ce qui m’a joué dans Symfony 2.0:
Remplacez le service twig.loader afin que nous puissions définir notre classe personnalisée:
twig.loader:
class: Acme\AppBundle\TwigLoader\MobileFilesystemLoader
arguments:
locator: "@templating.locator"
parser: "@templating.name_parser"
Et créez notre classe personnalisée, qui définit simplement le format "mob" sur les modèles dans le cas où le client est un appareil mobile:
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
}
}
Je suggérerais que cela ne soit pas mieux géré par le contrôleur, mais par les requêtes de média CSS, et de servir une feuille de style séparée à différentes classes de périphériques en fonction des résultats de cette requête de média CSS. Une bonne introduction ici: http://www.Adobe.com/devnet/dreamweaver/articles/introducing-media-queries.html
et je voudrais essayer de lire http://www.abookapart.com/products/responsive-web-design en détail. Certaines réflexions ont été faites depuis la publication du livre, mais cela vous mènera dans la bonne direction.
Alternative: https://github.com/suncat2000/MobileDetectBundle
Je l'ai trouvé assez bon par rapport à https://github.com/kbond/ZenstruckMobileBundle et https://github.com/liip/LiipThemeBundle
Je pense qu'il n'y a rien à voir avec symfony. Les modèles sont pour la vue. Vous pouvez y parvenir en utilisant différentes CSS pour le même modèle afin d’obtenir une présentation différente (modèle). J'utilise jQuery et CSS pour gérer différents périphériques. Vous voudrez peut-être consulter un code source de l'interface utilisateur à partir de http://themeforest.net/ ; spécifiquement ce template . Ceci est l'un gère un périphérique différent.
D'après mes expériences, vous pouvez, mais en spécifiant tout d'abord un format - vérifiez ces docs , ils pourront peut-être vous aider.