diff --git a/autoloader.php b/autoloader.php new file mode 100644 index 0000000..e1bf112 --- /dev/null +++ b/autoloader.php @@ -0,0 +1,21 @@ +checkConnection(); + if (!$connections[$name]->checkConnection()) + { + $connections[$name]->connect(); + } } else { @@ -82,9 +85,10 @@ private function __construct($name, $connectionParameters, $customOptions) $options = array_merge($defaultOptions, $customOptions); $this->name = $name; - $this->connection = self::connect($connectionParameters, $options); $this->connectionParameters = $connectionParameters; $this->connectionOptions = $options; + + $this->connect(); } private function __clone() @@ -286,36 +290,49 @@ public function getLastInsertId() return $this->connection->lastInsertId(); } - private function checkConnection() + public function checkConnection() { try { - $sum = $this->connection->query('SELECT 1 + 1')->fetchColumn(0); + // this throws an error (not an exception) if the connection has gone away; + // needs to be suppressed because we want only exceptions + $sum = @$this->connection->query('SELECT 1 + 1'); + + if ($sum instanceof \PDOStatement) + { + $sum = $sum->fetchColumn(0); + } + else + { + $sum = 0; + } if (intval($sum) !== 2) { - // Invalid result, try reconnecting because something is clearly wrong. - $this->connection = self::connect($this->connectionParameters, $this->connectionOptions); + // Invalid result, something is clearly wrong. + return false; } } catch (\Exception $e) { - // Connection may have timed out, try reconnecting. + // Connection may have timed out. // There is no single standard SQLSTATE code for "connection timed out", nor is there a built-in way to check this, // so we can only guess that that's what happened. - $this->connection = self::connect($this->connectionParameters, $this->connectionOptions); + return false; } + + return true; } - private static function connect($connectionParameters, $connectionOptions) + public function connect() { try { - return new \PDO( - self::buildDNSString($connectionParameters), - $connectionParameters['username'], - $connectionParameters['password'], - $connectionOptions + $this->connection = new \PDO( + self::buildDNSString($this->connectionParameters), + $this->connectionParameters['username'], + $this->connectionParameters['password'], + $this->connectionOptions ); } catch (\PDOException $e) diff --git a/test.php b/test.php index 0a5142c..edb593b 100644 --- a/test.php +++ b/test.php @@ -1,28 +1,6 @@ 'mysql', + 'username' => 'test', + 'password' => 'test', + 'database' => 'test', + ]); + // this is the mysql.ini variable that should be adjusted according to needs + // but it works via query as well + $handler->exec('SET SESSION wait_timeout = 1'); + + echo 'connection timeout set to 1 second, sleeping', PHP_EOL; + sleep(3); + + if ($handler->checkConnection()) + { + echo 'connection is good', PHP_EOL; + } + else + { + echo 'connection is down, reconnecting', PHP_EOL; + $handler->connect(); + } + + if ($handler->checkConnection()) + { + echo 'connection is now good', PHP_EOL; + } + else + { + echo 'connection is still down, failed to reconnect', PHP_EOL; + } +} +catch (DbException $e) +{ + echo $e->getMessage(), PHP_EOL; + die(); +}