2012-05-22 10 views
6

Uno dei miei requisiti per il mio progetto corrente è consentire a un utente di scegliere un fuso orario per il proprio account e quindi utilizzare questo fuso orario per tutte le funzionalità relative alla data/ora in tutto il intero sitoSymfony2: dove impostare un fuso orario definito dall'utente

Il mio modo di vedere, ho due opzioni:

  • Passo in un oggetto DateTimeZone al costruttore di DateTime per ogni nuovo DateTime
  • impostare il fuso orario predefinito utilizzando PHP date_default_timezone_set()

Sembra che usare date_default_timezone_set sia la strada da percorrere, ma non sono sicuro di dove dovrei impostarlo. Poiché il fuso orario sarà diverso da utente a utente e DateTime sono utilizzati in tutto il sito, ho bisogno di impostarlo da qualche parte che interesserà tutte le pagine.

Forse potrei scrivere un listener di eventi che lo imposta dopo un login riuscito? Se seguo questo approccio, rimarrà impostato su tutte le pagine o è impostato solo su una base per pagina?

Mi piacerebbe sapere come gli altri si avvicinerebbero a questo.

risposta

14

Sì, è possibile utilizzare un listener di eventi, agganciando l'evento kernel.request.

Ecco l'ascoltatore da uno dei miei progetti:

<?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, supponiamo che il mio server è impostato su "UTC" e l'utente a "America/Caracas". Con la tua soluzione, cosa succede quando un utente invia un datetime in qualche campo entità? Il datetime verrà memorizzato con il fuso orario dell'utente (senza modifiche rispetto al valore inserito dall'utente) o con il fuso orario del server (il valore è stato modificato in modo da corrispondere all'ora UTC)? –

+0

@David Dovresti solo archiviare le ore/date basate su UTC nel tuo database. In questo modo puoi sempre formattarlo correttamente per l'utente. – Luke