2012-05-22 45 views
6

Một trong những yêu cầu của tôi cho dự án hiện tại là cho phép người dùng chọn múi giờ cho tài khoản của họ và sau đó sử dụng múi giờ này cho tất cả các tính năng liên quan đến ngày/giờ toàn bộ trang web.Symfony2: Nơi đặt múi giờ do người dùng xác định

Con đường tôi nhìn thấy nó, tôi có hai lựa chọn:

  • đèo trong một đối tượng DateTimeZone để constructor DateTime cho mỗi DateTime mới
  • Đặt múi giờ mặc định sử dụng PHP của date_default_timezone_set()

Có vẻ như sử dụng date_default_timezone_set là cách để đi, nhưng tôi không chắc chắn chính xác nơi tôi nên đặt nó. Bởi vì múi giờ sẽ khác với người dùng với người dùng và DateTime được sử dụng trên toàn bộ trang web, tôi cần đặt nó ở một nơi nào đó mà nó sẽ ảnh hưởng đến tất cả các trang.

Có lẽ tôi có thể viết trình xử lý sự kiện đặt nó sau khi đăng nhập thành công? Nếu tôi sử dụng cách tiếp cận này, nó sẽ được đặt trên tất cả các trang hay nó chỉ được đặt trên cơ sở mỗi trang?

Tôi rất muốn nghe người khác sẽ tiếp cận điều này như thế nào.

Trả lời

14

Vâng, bạn có thể sử dụng trình xử lý sự kiện, hooking vào sự kiện kernel.request.

Đây là người biết lắng nghe từ một trong những dự án của tôi:

<?php 
namespace Vendor\Bundle\AppBundle\Listener; 

use Symfony\Component\Security\Core\SecurityContextInterface; 
use Doctrine\DBAL\Connection; 
use JMS\DiExtraBundle\Annotation\Service; 
use JMS\DiExtraBundle\Annotation\Observe; 
use JMS\DiExtraBundle\Annotation\InjectParams; 
use JMS\DiExtraBundle\Annotation\Inject; 

/** 
* @Service 
*/ 
class TimezoneListener 
{ 
    /** 
    * @var \Symfony\Component\Security\Core\SecurityContextInterface 
    */ 
    private $securityContext; 

    /** 
    * @var \Doctrine\DBAL\Connection 
    */ 
    private $connection; 

    /** 
    * @InjectParams({ 
    *  "securityContext" = @Inject("security.context"), 
    *  "connection"  = @Inject("database_connection") 
    * }) 
    * 
    * @param \Symfony\Component\Security\Core\SecurityContextInterface $securityContext 
    * @param \Doctrine\DBAL\Connection $connection 
    */ 
    public function __construct(SecurityContextInterface $securityContext, Connection $connection) 
    { 
     $this->securityContext = $securityContext; 
     $this->connection  = $connection; 
    } 

    /** 
    * @Observe("kernel.request") 
    */ 
    public function onKernelRequest() 
    { 
     if (!$this->securityContext->isGranted('ROLE_USER')) { 
      return; 
     } 

     $user = $this->securityContext->getToken()->getUser(); 
     if (!$user->getTimezone()) { 
      return; 
     } 

     date_default_timezone_set($user->getTimezone()); 
     $this->connection->query("SET timezone TO '{$user->getTimezone()}'"); 
    } 
} 
+3

@elnur, giả sử rằng máy chủ của tôi được thiết lập để "UTC" và người dùng "Mỹ/Caracas". Với giải pháp của bạn, điều gì sẽ xảy ra khi người dùng gửi một datetime trong một số trường thực thể? Thời gian được lưu trữ với múi giờ của người dùng (không có thay đổi so với giá trị mà người dùng đã nhập) hoặc với múi giờ của máy chủ (giá trị được thay đổi để khớp với thời gian UTC)? –

+0

@David Bạn chỉ nên lưu trữ thời gian/ngày dựa trên UTC trong cơ sở dữ liệu của mình. Bằng cách đó bạn luôn có thể định dạng chính xác nó cho người dùng. – Luke

Các vấn đề liên quan