2011-11-24 50 views
24

Có thể (và làm thế nào) đểSymfony 2 tải mẫu khác nhau tùy thuộc vào tính chất tác nhân người dùng

  • xác định nếu người dùng đang sử dụng một thiết bị di động
  • lực symfony 2 để tải mẫu khác nhau trong trường hợp đó
  • (và rơi trở lại html mẫu mặc định)

gì id thích làm được, để tải các mẫu khác nhau mà không sửa đổi bất kỳ bộ điều khiển nào.

CẬP NHẬT

Nó không phải là một phần phát hiện những vấn đề thực sự ở đây, nó thực sự không có gì để làm với symfony. Nó có thể được thực hiện (tải mẫu khác nhau) ở cấp bộ điều khiển:

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

Nhưng nó có thể được thực hiện trên toàn cầu? Giống như một dịch vụ, hoặc một cái gì đó mà thực hiện trước mỗi yêu cầu, và thực hiện thay đổi trong các quy tắc templating.

+0

Tôi không chắc chắn giải pháp sẽ liên quan đến khuôn khổ. Bạn đã kiểm tra http://www.hand-interactive.com/resources/detect-mobile-php.htm#download chưa? – FMaz008

Trả lời

22

Ok, vì vậy tôi không có một giải pháp đầy đủ nhưng một chút hơn nơi để tìm kiếm một :)

Bạn có thể chỉ nâng bốc hàng (dịch vụ) cho mặt hàng khuôn mẫu trong 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:   ~ 

Sau đó xác định các dịch vụ nạp được đề cập:

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

Sau đó xác định dịch vụ nạp của bạn lớp:

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

Như bạn có thể thấy đây không phải là giải pháp đầy đủ, nhưng tôi hy vọng điều này, ít nhất, hướng bạn đi đúng hướng.

EDIT: Chỉ cần phát hiện ra rằng có một bó với khả năng phát hiện điện thoại di động, với động cơ cành lá tùy chỉnh mà làm cho tập tin mẫu tùy thuộc vào một thiết bị gửi yêu cầu ZenstruckMobileBundle, mặc dù tôi không bao giờ sử dụng nó như vậy ... :)

+1

Liên kết FYI ZenstruckMobileBundle bị hỏng. Điều này hoạt động mặc dù: [http://zenstruck.com/projects/ZenstruckMobileBundle](http://zenstruck.com/projects/ZenstruckMobileBundle) –

+0

Ngoài ra còn có https://github.com/suncat2000/MobileDetectBundle cung cấp cho bạn công cụ cho nó quá –

0

Từ kinh nghiệm của tôi, bạn có thể nhưng bằng cách xác định một định dạng ở nơi đầu tiên - kiểm tra các docs, họ có thể để hỗ trợ bạn

0

tôi nghĩ là không có gì để làm với symfony. Mẫu dành cho VIEW. Bạn có thể đạt được điều này bằng cách sử dụng CSS khác nhau cho cùng một mẫu để có được bố trí khác nhau (mẫu). Tôi đang sử dụng jQuery và CSS để xử lý các thiết bị khác nhau. Bạn có thể muốn xem một số mã nguồn của giao diện người dùng từ http://themeforest.net/; cụ thể là template. Đây là một trong những thiết bị xử lý khác nhau.

1

Tôi khuyên rằng điều này không được xử lý tốt nhất bởi bộ điều khiển mà bằng truy vấn phương tiện CSS và phân phối biểu định kiểu riêng cho các lớp thiết bị khác nhau dựa trên kết quả của truy vấn phương tiện CSS đó. Một phần giới thiệu tốt tại đây: http://www.adobe.com/devnet/dreamweaver/articles/introducing-media-queries.html

và tôi sẽ thử đọc chi tiết một cách chi tiết hơn http://www.abookapart.com/products/responsive-web-design. Một số suy nghĩ đã được thực hiện kể từ khi cuốn sách được xuất bản, nhưng nó sẽ giúp bạn đi đúng hướng.

3

Bạn có thể sử dụng kernel.view trình xử lý sự kiện. Sự kiện này xảy ra khi bộ điều khiển trả về không có phản hồi, chỉ dữ liệu. Bạn có thể đặt phản hồi theo thuộc tính tác nhân người dùng. Ví dụ

Trong điều khiển của bạn,

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

    return $data; 
} 

Và trong kernel.view nghe sự kiện của bạn,

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

định nghĩa dịch vụ,

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

Đây là những gì đã làm các trick cho tôi trong Symfony 2.0:

Override dịch vụ twig.loader vì vậy chúng tôi có thể thiết lập lớp tùy chỉnh của chúng tôi:

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

Và tạo lớp tùy chỉnh của chúng tôi, chỉ đặt định dạng "mob" thành mẫu trong trường hợp máy khách là thiết bị di động:

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 
    } 
} 
Các vấn đề liên quan