【问题标题】:Symfony 2 load different template depending on user agent propertiesSymfony 2 根据用户代理属性加载不同的模板
【发布时间】:2012-01-05 15:49:15
【问题描述】:

有可能(以及如何)

  • 确定用户是否使用移动设备
  • 在这种情况下强制 symfony 2 加载不同的模板
  • (并回退默认的 html 模板)

id 喜欢做的是,在不修改任何控制器的情况下加载不同的模板。

更新

这里真正的问题不是检测部分,它真的与 symfony 无关。它可以在控制器级别完成(加载不同的模板):

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

但它可以在全球范围内完成吗?就像一个服务,或者在每个请求之前执行的东西,并在模板规则中进行更改。

【问题讨论】:

标签: php mobile symfony twig


【解决方案1】:

好的,所以我没有完整的解决方案,但比在哪里寻找一个多一点:)

您可以在 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:         ~

然后定义上面提到的加载器服务:

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

然后定义你的加载器服务类:

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

如您所见,这不是完整的解决方案,但我希望这至少可以为您指明正确的方向。

编辑:刚刚发现有一个具有移动检测功能的捆绑包,带有自定义树枝引擎,可根据发送请求的设备呈现模板文件 ZenstruckMobileBundle,虽然我从来没用过... :)

【讨论】:

【解决方案2】:

这就是我在 Symfony 2.0 中的诀窍:

覆盖 twig.loader 服务,以便我们设置自定义类:

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

并创建我们的自定义类,它只是将“mob”格式设置为模板,以防客户端是移动设备:

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

【讨论】:

    【解决方案3】:
    【解决方案4】:

    嗯,你可以使用LiipThemeBundle

    【讨论】:

      【解决方案5】:

      您可以使用kernel.view 事件监听器。当控制器不返回响应,仅返回数据时,此事件将起作用。您可以根据用户代理属性设置响应。例如

      在您的控制器中,

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

      在你的 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);
          }
      }
      

      服务定义,

      your_view_listener.listener:
          class: FQCN\Of\Listener\Class
          arguments:    [@templating]
          tags:
              - { name: kernel.event_listener, event: kernel.view, method: onKernelView }
      

      【讨论】:

        【解决方案6】:

        我建议最好不要由控制器处理,而是由 CSS 媒体查询处理,并根据 CSS 媒体查询的结果为不同类别的设备提供单独的样式表。 这里有一个很好的介绍: http://www.adobe.com/devnet/dreamweaver/articles/introducing-media-queries.html

        我会尝试详细阅读http://www.abookapart.com/products/responsive-web-design。自本书出版以来,已经进行了一些思考,但它会让你朝着正确的方向前进。

        【讨论】:

          【解决方案7】:

          我认为与 symfony 无关。模板用于 VIEW。您可以通过对同一模板使用不同的 CSS 来获得不同的布局(模板)来实现这一点。我正在使用 jQuery 和 CSS 来处理不同的设备。您可能想查看http://themeforest.net/ 的一些 UI 源代码;特别是这个template。这是一种处理不同的设备。

          【讨论】:

            【解决方案8】:

            根据我的经验,您可以,但首先要指定格式 - 检查这些 docs,他们可能会为您提供帮助

            【讨论】:

              猜你喜欢
              • 2012-10-07
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-09-01
              • 2023-03-22
              • 1970-01-01
              • 2014-03-16
              • 2022-12-07
              相关资源
              最近更新 更多