我在同一台服务器上运行多个 Symfony 应用程序,每个应用程序可能需要不同的时区。
对于 php,可以通过使用不同的 fpm 池并在池配置中设置时区来实现:
php_admin_value[date.timezone] = America/New_York
但是对于MySQL,我需要发出以下语句:
"SET time_zone = 'America/New_York';
作为连接后的第一个查询,或添加到 PDO 构造函数中的 $options 数组中:
PDO::MYSQL_ATTR_INIT_COMMAND => "SET time_zone = 'America/New_York';"
这怎么办?
您可以使用 PostConnect Doctrine 事件... https://www.doctrine-project.org/projects/doctrine-dbal/en/2.9/reference/events.html#postconnect-event
这对于在执行任何 sql 语句之前配置连接很有用。
一个例子可能是:
<?php
namespace App\EventListener;
use Doctrine\DBAL\Event\ConnectionEventArgs;
/**
* My initializer
*/
class MyPdoInitializerListener
{
public function postConnect(ConnectionEventArgs $args)
{
$args->getConnection()
->exec("SET time_zone = 'America/New_York'");
}
}
不要忘记将监听器添加到 services.yaml
# services.yaml
# ...
App\EventListener\MyPdoInitializerListener:
tags:
- { name: doctrine.event_listener, event: postConnect }
为了扩展 SilvioQ 的答案,我编写了以下代码片段以从 PHP 环境继承时区,假设之前调用了
date_default_timezone_set()
来设置正确的时区:
当命名时区
在 MySQL/MariaDB 中不可用并且您无法控制服务器时,此解决方案比命名时区(如
"America/New_York"
)具有优势。
public function postConnect(ConnectionEventArgs $args) {
$tz = new DateTimeZone(date_default_timezone_get());
$offset = $tz->getOffset(new DateTime('now'));
$abs = abs($offset);
$str = sprintf('%s%02d:%02d', $offset < 0 ? '-' : '+', intdiv($abs, 3600), intdiv($abs % 3600, 60));
$args->getConnection()->exec("SET time_zone = '$str'");
}