wake-up-neo.com

Symfony 2 lädt abhängig von den Eigenschaften des Benutzeragenten unterschiedliche Vorlagen

Ist es möglich (und wie)

  • ermitteln, ob ein Benutzer ein Mobilgerät verwendet
  • zwinge symfony 2, in diesem Fall eine andere Vorlage zu laden
  • (und auf die Standard-HTML-Vorlage zurückgreifen)

Was Sie tun möchten, ist, verschiedene Vorlagen zu laden, ohne einen Controller zu ändern.

UPDATE

Hier ging es nicht um die Erkennung, sondern um Symfony. Dies kann auf Controller-Ebene erfolgen (andere Vorlage laden):

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

Aber kann es global durchgeführt werden? Wie ein Dienst oder etwas, das vor jeder Anforderung ausgeführt wird und Änderungen an den Vorlagenregeln vornimmt.

25
user1063963

Ok, also ich habe keine vollständige Lösung, aber ein bisschen mehr, als wo ich nach einer suchen soll :)

Sie können in app/config/config.yml Loader (Dienste) für das Vorlagenelement angeben

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:         ~

Dann definieren Sie den erwähnten Laderservice:

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

Danach definieren Sie Ihre Loader-Serviceklasse:

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

Wie Sie sehen, ist dies nicht die vollständige Lösung, aber ich hoffe, dass dies zumindest Sie in die richtige Richtung weist.

BEARBEITEN: Ich habe gerade herausgefunden, dass es ein Bundle mit mobilen Erkennungsfunktionen gibt, mit einer benutzerdefinierten Zweig-Engine, die die Vorlagendatei abhängig von einem Gerät rendert, das die Anfrage gesendet hat ZenstruckMobileBundle , obwohl ich es nie so verwendet habe ... :)

23

Nun, Sie können LiipThemeBundle verwenden.

6

Sie können den Ereignis-Listener kernel.view verwenden. Dieses Ereignis wird ausgelöst, wenn der Controller keine Antwort, sondern nur Daten zurückgibt. Sie können die Antwort entsprechend der Eigenschaft des Benutzeragenten festlegen. Zum Beispiel

In Ihrem Controller,

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

    return $data;
}

Und die in Ihrem kernel.view Ereignis-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 }
3
Mun Mun Das

Folgendes hat mir in Symfony 2.0 geholfen:

Überschreiben Sie den twig.loader-Service, damit wir unsere benutzerdefinierte Klasse festlegen können:

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

Und erstellen Sie unsere benutzerdefinierte Klasse, die nur das Mob-Format für die Vorlagen festlegt, falls der Client ein mobiles Gerät ist:

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
    }
 }
2
nachopas

Ich würde vorschlagen, dass dies nicht am besten vom Controller, sondern von CSS-Medienabfragen gehandhabt wird und basierend auf den Ergebnissen dieser CSS-Medienabfrage ein separates Stylesheet für verschiedene Geräteklassen bereitgestellt wird. Ein gutes Intro hier: http://www.Adobe.com/devnet/dreamweaver/articles/introducing-media-queries.html

und ich würde versuchen zu lesen http://www.abookapart.com/products/responsive-web-design sehr detailliert. Seit dem Erscheinen des Buches wurde einiges nachgedacht, aber es wird Ihnen helfen, die richtige Richtung einzuschlagen.

1
Jeremy Anderson
0
ihsan

Ich denke, das hat nichts mit Symfony zu tun. Vorlagen sind für die VIEW. Sie können dies erreichen, indem Sie unterschiedliche CSS für dieselbe Vorlage verwenden, um ein anderes Layout (Vorlage) zu erhalten. Ich benutze jQuery und CSS, um mit verschiedenen Geräten umzugehen. Vielleicht möchten Sie sich einen Quellcode der Benutzeroberfläche ansehen: http://themeforest.net/ ; speziell diese Vorlage . Dies ist ein behandelt anderes Gerät.

0
PMoubed

Nach meinen Erfahrungen können Sie aber, indem Sie zunächst ein Format angeben - überprüfen Sie diese docs , sie können Ihnen möglicherweise behilflich sein

0
Matt