diff --git a/src/Mysqli/MysqliDriver.php b/src/Mysqli/MysqliDriver.php index 0d55bfb6..b7705e48 100644 --- a/src/Mysqli/MysqliDriver.php +++ b/src/Mysqli/MysqliDriver.php @@ -202,7 +202,10 @@ public function connect() throw new UnsupportedAdapterException('The MySQLi extension is not available'); } - $this->connection = mysqli_init(); + // Enable mysqli error reporting + mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); + + $this->connection = new \mysqli(); $connectionFlags = 0; @@ -232,21 +235,21 @@ public function connect() ); } - // Attempt to connect to the server, use error suppression to silence warnings and allow us to throw an Exception separately. - $connected = @$this->connection->real_connect( - $this->options['host'], - $this->options['user'], - $this->options['password'], - null, - $this->options['port'], - $this->options['socket'], - $connectionFlags - ); - - if (!$connected) { + try { + $this->connection->real_connect( + $this->options['host'], + $this->options['user'], + $this->options['password'], + null, + $this->options['port'], + $this->options['socket'], + $connectionFlags + ); + } catch (\mysqli_sql_exception $e) { throw new ConnectionFailureException( - 'Could not connect to database: ' . $this->connection->connect_error, - $this->connection->connect_errno + 'Could not connect to database: ' . $e->getMessage(), + $e->getCode(), + $e ); } @@ -783,8 +786,10 @@ public function select($database) return false; } - if (!$this->connection->select_db($database)) { - throw new ConnectionFailureException('Could not connect to database.'); + try { + $this->connection->select_db($database); + } catch (\mysqli_sql_exception $e) { + throw new ConnectionFailureException('Could not connect to database: ' . $e->getMessage(), $e->getCode(), $e); } return true; @@ -810,20 +815,26 @@ public function setUtf() // Which charset should I use, plain utf8 or multibyte utf8mb4? $charset = $this->utf8mb4 && $this->options['utf8mb4'] ? 'utf8mb4' : 'utf8'; - $result = @$this->connection->set_charset($charset); - - /* - * If I could not set the utf8mb4 charset then the server doesn't support utf8mb4 despite claiming otherwise. This happens on old MySQL - * server versions (less than 5.5.3) using the mysqlnd PHP driver. Since mysqlnd masks the server version and reports only its own we - * can not be sure if the server actually does support UTF-8 Multibyte (i.e. it's MySQL 5.5.3 or later). Since the utf8mb4 charset is - * undefined in this case we catch the error and determine that utf8mb4 is not supported! - */ - if (!$result && $this->utf8mb4 && $this->options['utf8mb4']) { - $this->utf8mb4 = false; - $result = @$this->connection->set_charset('utf8'); + try { + $this->connection->set_charset($charset); + } catch (\mysqli_sql_exception) { + /* + * If I could not set the utf8mb4 charset then the server doesn't support utf8mb4 despite claiming otherwise. This happens on old MySQL + * server versions (less than 5.5.3) using the mysqlnd PHP driver. Since mysqlnd masks the server version and reports only its own we + * can not be sure if the server actually does support UTF-8 Multibyte (i.e. it's MySQL 5.5.3 or later). Since the utf8mb4 charset is + * undefined in this case we catch the error and determine that utf8mb4 is not supported! + */ + if ($this->utf8mb4 && $this->options['utf8mb4']) { + $this->utf8mb4 = false; + try { + $this->connection->set_charset('utf8'); + } catch (\mysqli_sql_exception) { + return false; + } + } } - return $result; + return true; } /** @@ -841,8 +852,11 @@ public function transactionCommit($toSavepoint = false) if (!$toSavepoint || $this->transactionDepth <= 1) { $this->connect(); - if ($this->connection->commit()) { + try { + $this->connection->commit(); $this->transactionDepth = 0; + } catch (\mysqli_sql_exception) { + // TODO: Handle commit failure? } return; @@ -866,8 +880,11 @@ public function transactionRollback($toSavepoint = false) if (!$toSavepoint || $this->transactionDepth <= 1) { $this->connect(); - if ($this->connection->rollback()) { + try { + $this->connection->rollback(); $this->transactionDepth = 0; + } catch (\mysqli_sql_exception) { + // TODO: Handle rollback failure? } return; @@ -922,12 +939,11 @@ protected function executeUnpreparedQuery($sql) { $this->connect(); - $cursor = $this->connection->query($sql); - - // If an error occurred handle it. - if (!$cursor) { - $errorNum = (int) $this->connection->errno; - $errorMsg = (string) $this->connection->error; + try { + $this->connection->query($sql); + } catch (\mysqli_sql_exception $e) { + $errorNum = $e->getCode(); + $errorMsg = $e->getMessage(); // Check if the server was disconnected. if (!$this->connected()) { @@ -935,7 +951,7 @@ protected function executeUnpreparedQuery($sql) // Attempt to reconnect. $this->connection = null; $this->connect(); - } catch (ConnectionFailureException $e) { + } catch (ConnectionFailureException) { // If connect fails, ignore that exception and throw the normal exception. throw new ExecutionFailureException($sql, $errorMsg, $errorNum); } @@ -948,12 +964,6 @@ protected function executeUnpreparedQuery($sql) throw new ExecutionFailureException($sql, $errorMsg, $errorNum); } - $this->freeResult(); - - if ($cursor instanceof \mysqli_result) { - $cursor->free_result(); - } - return true; } diff --git a/src/Mysqli/MysqliStatement.php b/src/Mysqli/MysqliStatement.php index 040e2cb7..3e8118bb 100644 --- a/src/Mysqli/MysqliStatement.php +++ b/src/Mysqli/MysqliStatement.php @@ -135,10 +135,10 @@ public function __construct(\mysqli $connection, string $query) $query = $this->prepareParameterKeyMapping($query); - $this->statement = $connection->prepare($query); - - if (!$this->statement) { - throw new PrepareStatementFailureException($this->connection->error, $this->connection->errno); + try { + $this->statement = $connection->prepare($query); + } catch (\mysqli_sql_exception $e) { + throw new PrepareStatementFailureException($e->getMessage(), $e->getCode(), $e); } } @@ -397,19 +397,21 @@ public function execute(?array $parameters = null) array_unshift($params, implode('', $types)); - if (!\call_user_func_array([$this->statement, 'bind_param'], $params)) { - throw new PrepareStatementFailureException($this->statement->error, $this->statement->errno); + try { + \call_user_func_array([$this->statement, 'bind_param'], $params); + } catch (\Exception $e) { + throw new PrepareStatementFailureException($e->getMessage(), $e->getCode(), $e); } } elseif ($parameters !== null) { - if (!$this->bindValues($parameters)) { - throw new PrepareStatementFailureException($this->statement->error, $this->statement->errno); + try { + $this->bindValues($parameters); + } catch (\Exception $e) { + throw new PrepareStatementFailureException($e->getMessage(), $e->getCode(), $e); } } try { - if (!$this->statement->execute()) { - throw new ExecutionFailureException($this->query, $this->statement->error, $this->statement->errno); - } + $this->statement->execute(); } catch (\Throwable $e) { throw new ExecutionFailureException($this->query, $e->getMessage(), $e->getCode(), $e); } @@ -442,9 +444,7 @@ public function execute(?array $parameters = null) $refs[$key] =& $value; } - if (!\call_user_func_array([$this->statement, 'bind_result'], $refs)) { - throw new \RuntimeException($this->statement->error, $this->statement->errno); - } + \call_user_func_array([$this->statement, 'bind_result'], $refs); } $this->result = true; @@ -488,10 +488,6 @@ public function fetch(?int $fetchStyle = null, int $cursorOrientation = FetchOri return false; } - if ($values === false) { - throw new \RuntimeException($this->statement->error, $this->statement->errno); - } - switch ($fetchStyle) { case FetchMode::NUMERIC: return $values; @@ -543,7 +539,11 @@ public function fetchColumn($columnIndex = 0) */ private function fetchData() { - $return = $this->statement->fetch(); + try { + $return = $this->statement->fetch(); + } catch (\Throwable $e) { + throw new \RuntimeException($e->getMessage(), $e->getCode(), $e); + } if ($return === true) { $values = [];