2017-02-22 48 views
0

我需要改進我在Symfony2中完成的工作的應用程序,現在我們正在擴展到國際級別,並且我們必須實施時區系統以便每個用戶可以修改他們將收到通知和其他警報的日期。我們的原始時區是UTC + 1(歐洲/馬德里),因此我們必須將時間段中的日期保存在數據庫中。但是當涉及到應用程序時,它應該能夠在設置中顯示用戶配置的時間。如何在Symfony2中以用戶登錄方式編程設置DateTime時區

我如何在Symfony 2中實現它,這樣我就不必修改所有的控制器和樹枝模板了?

它可以在事件監聽器中完成嗎?

+0

那叫'date_default_timezone_set(「Asia/Bangkok」);'作爲你的例子的一部分呢? 'app.php'和'app_dev.php',但你可以稱它爲適合你的應用程序。 – LBA

+0

感謝您的回答:)。所以調用該函數將影響DDBB中插入dateTime? – didix16

回答

-1

1)設置默認時區,即在監聽kernel.request事件的事件監聽器中。

2)創建監聽security.interactive_login事件的事件監聽器,並從事件中提取用戶,然後獲取他自己的時區設置並應用。 (An example

+0

好的,謝謝!我現在要試一試。 – didix16

1

最後,我找到了一個解決方案,獲取您的信息並搜索類似的東西,特別是 - >how to get the type of a doctrine entity property幫助我開發了最終的代碼。

這裏是我做了什麼:

  1. 我已經擴展主義的日期時間爲一個新的類UTCDateTimeType:

    use Doctrine\DBAL\Platforms\AbstractPlatform; 
    use Doctrine\DBAL\Types\ConversionException; 
    use Doctrine\DBAL\Types\DateTimeType; 
    
    class UTCDateTimeType extends DateTimeType { 
    
        static private $utc; 
    
        static function getUtc(){ 
    
         return self::$utc; 
        } 
    
        public function convertToDatabaseValue($value, AbstractPlatform $platform) 
        { 
         if ($value instanceof \DateTime) { 
          $value->setTimezone(self::getUtc()); 
         } 
    
         return parent::convertToDatabaseValue($value, $platform); 
        } 
    
        public function convertToPHPValue($value, AbstractPlatform $platform) 
        { 
    
         if (null === $value || $value instanceof \DateTime) { 
          return $value; 
         } 
    
         $converted = \DateTime::createFromFormat(
          $platform->getDateTimeFormatString(), 
          $value, 
          self::$utc ? self::$utc : self::$utc = new \DateTimeZone('Europe/Madrid') 
         ); 
    
         if (! $converted) { 
          throw ConversionException::conversionFailedFormat(
           $value, 
           $this->getName(), 
           $platform->getDateTimeFormatString() 
          ); 
         } 
    
         return $converted; 
        } 
    } 
    

    所以當GET或persit日期時間的數據,這是永諾在我的UTC時區。

  2. 然後,自舉ORM之前,我已經overrided的時間類型:

    Type::overrideType('datetime', UTCDateTimeType::class); 
    Type::overrideType('datetimetz', UTCDateTimeType::class); 
    
  3. 我修改了用戶實體有一個時區場(PHP時區標識符)

  4. 在LoginListener - > onSecurityInteractiveLogin上,我注入了會話,當用戶登錄時,我在Session中爲用戶時區字段設置了一個「timezone」變量。

    public function onSecurityInteractiveLogin(InteractiveLoginEvent $event){ 
        $user = $event->getAuthenticationToken()->getUser(); 
        $this->session->set("timezone",new \DateTimeZone($user->getTimeZone())); 
        // ... 
    } 
    
  5. 我提出其聽負荷後學說事件(當一個實體完全從DDBB加載觸發)

    use Symfony\Component\Routing\RouterInterface; 
    use Symfony\Component\HttpFoundation\Session\Session; 
    use Symfony\Component\Translation\TranslatorInterface; 
    use Doctrine\ORM\Event\LifecycleEventArgs; 
    use Doctrine\Common\Annotations\AnnotationReader; 
    
    class TimeZoneListener { 
    
        protected $session; 
    
        protected $container; 
    
        protected $router; 
    
        protected $securityContext; 
    
        protected $translator; 
    
        protected $docReader; 
    
        public function __construct(RouterInterface $router, Session $session, TranslatorInterface $translator, $container){ 
    
         $this->session = $session; 
         $this->router = $router; 
         $this->translator = $translator; 
         $this->container = $container; 
         $this->docReader = new AnnotationReader(); 
        } 
    
        public function postLoad(LifecycleEventArgs $args){ 
    
         $reader = $this->docReader; 
         $entity = $args->getEntity(); 
         $reflect = new \ReflectionClass($entity); 
    
         $props = $reflect->getProperties(); 
    
         foreach($props as $prop){ 
    
          $docInfos = $reader->getPropertyAnnotations($prop); 
          foreach($docInfos as $info){ 
    
           if(!$info instanceof \Doctrine\ORM\Mapping\Column) continue; 
           if($info->type !== "datetime") continue; 
    
           $getDateMethod = 'get'.ucfirst($prop->getName()); 
    
           $val = $entity->{$getDateMethod}(); 
           if($val){ 
            $val->setTimeZone($this->session->get("timezone") ? $this->session->get("timezone") : new \DateTimeZone("Europe/Madrid")); 
    
           } 
    
          } 
         } 
        } 
    } 
    
  6. 負荷後方法我搜索的每個屬性一個TimeZoneListener鍵入datetime然後我設置爲登錄用戶timeZone(以前設置爲登錄進入會話)

  7. 現在,每次加載實體時,在達到日期時間字段時,在呈現階段,日期時間偏移量已成功應用,並且每個用戶都顯示爲已預覽。

+0

國際海事組織,引用[官方原則文件](http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/cookbook/working-with-datetime.html)將是有道理的;-) – Lashae

相關問題