/** * Attemps to create a PDO object based on the parameters and configured * to throw exceptions on errors. * * @param string $dsn * @param string $user * @param string $password * @param array $attrs = null * @return PDO */ public static function getDBConn($dsn, $user, $password, array $attrs = null) { // First check the cache $dbKey = md5(implode(chr(31), array($dsn, $user, $password, serialize($attrs)))); if (array_key_exists($dbKey, self::$_dbCache)) { return self::$_dbCache[$dbKey]['db']; } try { $dbConn = new PDO($dsn, $user, $password, $attrs); $dbConn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // Get the time zone offset $q = <<<EOF SELECT TIMESTAMPDIFF( SECOND, CONVERT_TZ(NOW(), @@session.time_zone, '+00:00'), NOW() ) EOF; $stmt = $dbConn->query($q); $offset = $stmt->fetchColumn(); /* This will come out as a string, which is necessary because we need to be able to distinguish 0 and null. */ if ($offset === null) { // This really shouldn't happen throw new UnexpectedValueException('Got unexpected result when querying database for time ' . 'zone offset.'); } // Now that that test is done, we can cast as an int $offset = (int) $offset; if (self::$_dbTimeZoneOffset === null) { /* If this property is null, but we've already cached a database connection, it means we've already encountered multiple different time zone offsets. */ if (!self::$_dbCache) { self::$_dbTimeZoneOffset = $offset; } } elseif (self::$_dbTimeZoneOffset !== $offset) { self::$_dbTimeZoneOffset = null; } self::$_dbCache[$dbKey] = array('db' => $dbConn, 'time_zone_offset' => $offset); return $dbConn; } catch (PDOException $e) { throw new RuntimeException('Caught PDOException.', null, $e); } }