7

我对当前项目的要求之一是允许用户为其帐户选择一个时区,然后将这个时区用于整个站点的所有与日期/时间相关的功能。

在我看来,我有两个选择:

  • 为每个新的 DateTime 传递一个 DateTimeZone 对象到 DateTime 的构造函数
  • 使用 PHP 设置默认时区date_default_timezone_set()

似乎使用 date_default_timezone_set 是要走的路,但我不确定我应该在哪里设置它。因为时区因用户而异,并且整个站点都使用 DateTime,所以我需要将其设置在会影响所有页面的位置。

也许我可以编写一个事件监听器,在成功登录后设置它?如果我采用这种方法,它会在所有页面上保持设置还是仅在每页的基础上设置?

我很想听听其他人会如何处理这个问题。

4

1 回答 1

15

是的,您可以使用事件侦听器来挂钩kernel.request事件。

这是我的一个项目中的听众:

<?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()}'");
    }
}
于 2012-05-22T09:35:20.433 回答