From 1e2c9e5039bafcc6927fe29f43440829135e682c Mon Sep 17 00:00:00 2001 From: John Robinson Date: Mon, 16 Sep 2024 21:23:17 -0400 Subject: [PATCH] v5.0.0 updates (#8) * Updated calculation of query durations * v5.0.0 updates * Updated documentation --- CHANGELOG.md | 17 ++++ docs/README.md | 66 ++++++++-------- docs/getting-started.md | 5 +- src/Db.php | 169 ++++++++++++++++++++++------------------ src/DbFactory.php | 27 ++----- 5 files changed, 153 insertions(+), 131 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bab88eb..19ab028 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `Fixed` for any bug fixes. - `Security` in case of vulnerabilities +## [5.0.0] - 2024.09.16 + +### Added + +- Added `setQueryTime` method. + +### Changed + +- Updated method for calculating query durations to be more accurate. +- Updated `getQueryTime` and `getTotalQueries` methods to accept a specific database name. +- Updated `DbFactory::create` method to not require a specific `default` database. + +### Removed + +- Removed concept of "default" and "current" database in favor of simply using "current". +- Removed `getDefaultConnectionName` method. + ## [4.0.1] - 2024.09.10 ### Fixed diff --git a/docs/README.md b/docs/README.md index d08a806..0207b03 100644 --- a/docs/README.md +++ b/docs/README.md @@ -26,7 +26,6 @@ Once an instance is created, you can begin using Simple PDO. - [useConnection](#useconnection) - [getConnection](#getconnection) - [getCurrentConnection](#getcurrentconnection) -- [getDefaultConnectionName](#getdefaultconnectionname) - [getCurrentConnectionName](#getcurrentconnectionname) - [getConnectionNames](#getconnectionnames) - [connectionExists](#connectionexists) @@ -53,6 +52,7 @@ Once an instance is created, you can begin using Simple PDO. - [getLastParameters](#getlastparameters) - [rowCount](#rowcount) - [lastInsertId](#lastinsertid) +- [setQueryTime](#setquerytime) - [getQueryTime](#getquerytime) - [getTotalQueries](#gettotalqueries) @@ -68,8 +68,7 @@ Add a PDO instance. - `$pdo` (PDO) - `$db_name` (string): Name must be unique -- `$make_current = false` (bool): Use this connection for the next query only -- `$make_default = false` (bool): Use this connection for each subsequent query +- `$make_current = false` (bool): Use this connection for all subsequent queries **Returns:** @@ -97,13 +96,11 @@ try { **Description:** -Set given database name as current for the next query only. -After the next query, the current database will automatically revert to the default database. +Use a given database connection for all subsequent queries. **Parameters:** - `$db_name` (string) -- `$make_default = false` (bool) **Returns:** @@ -181,33 +178,11 @@ $pdo = $db->getCurrentConnection();
-### getDefaultConnectionName - -**Description:** - -Returns name of the default database. - -**Parameters:** - -- None - -**Returns:** - -- (string) - -**Example:** - -```php -echo $db->getDefaultConnectionName(); -``` - -
- ### getCurrentConnectionName **Description:** -Returns name of the database currently being used. +Returns name of the current database connection. **Parameters:** @@ -686,15 +661,42 @@ echo $db->lastInsertId();
+### setQueryTime + +**Description:** + +Add a query time to be tracked using `getQueryTime` and `getTotalQueries`. +This is helpful to track queries using the [query builder](query-builder.md). + +**Parameters:** + +- `$db_name` (string) +- `$duration = 0` (float): Microseconds as float + +**Returns:** + +- (void) + +**Example:** + +```php +$start_time = microtime(true); + +// Perform a query outside the Db class + +$db->setQueryTime('backup', microtime(true) - $start_time); +``` + ### getQueryTime **Description:** -Returns the total time elapsed in seconds for all queries executed for the current database. +Returns the total time elapsed in seconds for all queries executed for a given database. **Parameters:** - `$decimals = 3` (int): Number of decimal points to return +- `$db_name = ''` (string): Leaving this parameter blank will return the time elapsed for all database connections **Returns:** @@ -712,11 +714,11 @@ echo $db->getQueryTime(); **Description:** -Returns the total number of queries executed for the current database. +Returns the total number of queries executed for a given database. **Parameters:** -- None +- `$db_name = ''` (string): Leaving this parameter blank will return the total queries for all database connections **Returns:** diff --git a/docs/getting-started.md b/docs/getting-started.md index 499aa0f..8651e2e 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -46,7 +46,6 @@ use Bayfront\SimplePdo\Exceptions\SimplePDOException; $config = [ 'primary' => [ // Connection name - 'default' => true, // One connection on the array must be defined as default 'adapter' => 'MySql', // Adapter to use 'host' => 'DB_HOST', 'port' => 3306, @@ -74,5 +73,5 @@ try { ``` The array keys define the connection names. -Each name must be unique. -One connection must be defined as `default`, and each connection must specify a valid adapter. \ No newline at end of file +Each name must be unique, and each connection must specify a valid adapter. +The first listed connection name in the array will be set as the current database. \ No newline at end of file diff --git a/src/Db.php b/src/Db.php index 171ab76..44aa8f6 100644 --- a/src/Db.php +++ b/src/Db.php @@ -2,6 +2,7 @@ namespace Bayfront\SimplePdo; +use Bayfront\ArrayHelpers\Arr; use Bayfront\SimplePdo\Exceptions\InvalidDatabaseException; use PDO; use PDOStatement; @@ -10,7 +11,6 @@ class Db { private static array $db_connections = []; // Db connections as PDO objects - private string $default_db_name; private string $current_db_name; public const DB_DEFAULT = 'default'; @@ -18,7 +18,7 @@ class Db /** * Constructor. * - * Sets given PDO instance as current and default database. + * Sets given PDO instance as current database connection. * * @param PDO $pdo * @param string $db_name @@ -26,7 +26,6 @@ class Db public function __construct(PDO $pdo, string $db_name = self::DB_DEFAULT) { self::$db_connections[$db_name] = $pdo; - $this->default_db_name = $db_name; $this->current_db_name = $db_name; } @@ -48,18 +47,6 @@ private function disconnectAll(): void } } - /** - * Returns PDO object for current database name and resets current connection to default. - * - * @return PDO - */ - private function getCurrentConnectionAndReset(): PDO - { - $current = self::$db_connections[$this->current_db_name]; - $this->current_db_name = $this->default_db_name; // Reset current connection to default - return $current; - } - /* * |-------------------------------------------------------------------------- * | Database connections @@ -71,12 +58,11 @@ private function getCurrentConnectionAndReset(): PDO * * @param PDO $pdo * @param string $db_name (Name must be unique) - * @param bool $make_current (Use this connection for the next query only) - * @param bool $make_default (Use this connection for each subsequent query) + * @param bool $make_current (Use this connection for all subsequent queries) * @return self * @throws InvalidDatabaseException */ - public function addConnection(PDO $pdo, string $db_name, bool $make_current = false, bool $make_default = false): self + public function addConnection(PDO $pdo, string $db_name, bool $make_current = false): self { if (isset(self::$db_connections[$db_name])) { @@ -89,34 +75,24 @@ public function addConnection(PDO $pdo, string $db_name, bool $make_current = fa $this->current_db_name = $db_name; } - if (true === $make_default) { - $this->default_db_name = $db_name; - } - return $this; } /** - * Set given database name as current for the next query only. - * After the next query, the current database will automatically revert to the default database. + * Use a given database connection for all subsequent queries. * * @param string $db_name - * @param bool $make_default * @return self * @throws InvalidDatabaseException */ - public function useConnection(string $db_name, bool $make_default = false): self + public function useConnection(string $db_name): self { if (!isset(self::$db_connections[$db_name])) { throw new InvalidDatabaseException('Database is not defined'); } - if (true === $make_default) { - $this->default_db_name = $db_name; - } - $this->current_db_name = $db_name; return $this; @@ -156,17 +132,7 @@ public function getCurrentConnection(): PDO } /** - * Returns name of the default database. - * - * @return string - */ - public function getDefaultConnectionName(): string - { - return $this->default_db_name; - } - - /** - * Returns name of the database currently being used. + * Returns name of the current database connection. * * @return string */ @@ -213,13 +179,34 @@ public function connectionExists(string $db_name): bool * * @return void */ - private function beginQuery(): void + private function reset(): void { $this->query_start = microtime(true); $this->stmt = NULL; $this->raw_query = ''; } + /** + * Begin, prepare and execute query. + * + * @param string $query + * @param array $params + * @return bool + */ + private function executeQuery(string $query, array $params = []): bool + { + $this->reset(); + + $this->stmt = $this->prepare($query); + + $this->raw_query = $query; + + $this->bindParams($params); + + return $this->stmt->execute(); + + } + /** * Prepares a statement for execution and returns a statement object. * @@ -228,7 +215,7 @@ private function beginQuery(): void */ private function prepare(string $query): PDOStatement { - return $this->getCurrentConnectionAndReset()->prepare($query); // PDOStatement object + return $this->getCurrentConnection()->prepare($query); // PDOStatement object } /** @@ -284,15 +271,7 @@ private function bindParams(array $params): void public function query(string $query, array $params = []): bool { - $this->beginQuery(); - - $this->stmt = $this->prepare($query); - - $this->raw_query = $query; - - $this->bindParams($params); - - $return = $this->stmt->execute(); + $return = $this->executeQuery($query, $params); $this->query_durations[$this->current_db_name][] = microtime(true) - $this->query_start; // Record query duration @@ -311,13 +290,17 @@ public function query(string $query, array $params = []): bool public function select(string $query, array $params = [], bool $return_array = true): mixed { - $this->query($query, $params); + $this->executeQuery($query, $params); if ($return_array) { - return $this->stmt->fetchAll(PDO::FETCH_ASSOC); + $return = $this->stmt->fetchAll(PDO::FETCH_ASSOC); + } else { + $return = $this->stmt->fetchAll(PDO::FETCH_OBJ); } - return $this->stmt->fetchAll(PDO::FETCH_OBJ); + $this->query_durations[$this->current_db_name][] = microtime(true) - $this->query_start; // Record query duration + + return $return; } @@ -332,13 +315,17 @@ public function select(string $query, array $params = [], bool $return_array = t public function row(string $query, array $params = [], bool $return_array = true): mixed { - $this->query($query, $params); + $this->executeQuery($query, $params); if ($return_array) { - return $this->stmt->fetch(PDO::FETCH_ASSOC); + $return = $this->stmt->fetch(PDO::FETCH_ASSOC); + } else { + $return = $this->stmt->fetch(PDO::FETCH_OBJ); } - return $this->stmt->fetch(PDO::FETCH_OBJ); + $this->query_durations[$this->current_db_name][] = microtime(true) - $this->query_start; // Record query duration + + return $return; } @@ -351,8 +338,15 @@ public function row(string $query, array $params = [], bool $return_array = true */ public function single(string $query, array $params = []): mixed { - $this->query($query, $params); - return $this->stmt->fetchColumn(); + + $this->executeQuery($query, $params); + + $return = $this->stmt->fetchColumn(); + + $this->query_durations[$this->current_db_name][] = microtime(true) - $this->query_start; // Record query duration + + return $return; + } /** @@ -366,7 +360,7 @@ public function single(string $query, array $params = []): mixed public function insert(string $table, array $values, bool $overwrite = true): bool { - $this->beginQuery(); + $this->reset(); $query = 'INSERT INTO ' . $table . ' ('; @@ -423,7 +417,7 @@ public function insert(string $table, array $values, bool $overwrite = true): bo public function update(string $table, array $values, array $conditions): bool { - $this->beginQuery(); + $this->reset(); $query = 'UPDATE ' . $table . ' SET '; @@ -486,7 +480,7 @@ public function update(string $table, array $values, array $conditions): bool public function delete(string $table, array $conditions): bool { - $this->beginQuery(); + $this->reset(); /** @noinspection SqlWithoutWhere */ @@ -538,7 +532,7 @@ public function delete(string $table, array $conditions): bool public function count(string $table, array $conditions = []): int { - $this->beginQuery(); + $this->reset(); $query = 'SELECT COUNT(*) FROM ' . $table; @@ -570,9 +564,11 @@ public function count(string $table, array $conditions = []): int $this->stmt->execute(array_values($conditions)); + $return = (int)$this->stmt->fetchColumn(); + $this->query_durations[$this->current_db_name][] = microtime(true) - $this->query_start; // Record query duration - return (int)$this->stmt->fetchColumn(); + return $return; } @@ -607,7 +603,7 @@ public function exists(string $table, array $conditions = []): bool public function sum(string $table, string $column, array $conditions = []): int { - $this->beginQuery(); + $this->reset(); $query = 'SELECT SUM(' . $column . ') FROM ' . $table; @@ -639,9 +635,11 @@ public function sum(string $table, string $column, array $conditions = []): int $this->stmt->execute(array_values($conditions)); + $return = (int)$this->stmt->fetchColumn(); + $this->query_durations[$this->current_db_name][] = microtime(true) - $this->query_start; // Record query duration - return (int)$this->stmt->fetchColumn(); + return $return; } @@ -722,7 +720,7 @@ public function rowCount(): int } /** - * Returns the ID of the last inserted row + * Returns the ID of the last inserted row. * * @return string */ @@ -732,34 +730,53 @@ public function lastInsertId(): string } /** - * Returns the total time elapsed in seconds for all queries executed for the current database. + * Add query time to be tracked using getQueryTime and getTotalQueries. + * This is helpful to track queries using the query builder. + * + * @param string $db_name + * @param float $duration (Microseconds as float) + * @return void + */ + public function setQueryTime(string $db_name, float $duration = 0): void + { + $this->query_durations[$db_name][] = $duration; + } + + /** + * Returns the total time elapsed in seconds for all queries executed for a given database. * * @param int $decimals (Number of decimal points to return) + * @param string $db_name (Leaving this parameter blank will return the time elapsed for all database connections) * @return float */ - public function getQueryTime(int $decimals = 3): float + public function getQueryTime(int $decimals = 3, string $db_name = ''): float { - if (!isset($this->query_durations[$this->current_db_name])) { + if ($db_name == '') { + return number_format((float)array_sum(Arr::dot($this->query_durations)), $decimals); + } else if (!isset($this->query_durations[$db_name])) { return 0; } - return number_format((float)array_sum($this->query_durations[$this->current_db_name]), $decimals); + return number_format((float)array_sum($this->query_durations[$db_name]), $decimals); } /** - * Returns the total number of queries executed for the current database. + * Returns the total number of queries executed for a given database. * + * @param string $db_name (Leaving this parameter blank will return the total queries for all database connections) * @return int */ - public function getTotalQueries(): int + public function getTotalQueries(string $db_name = ''): int { - if (!isset($this->query_durations[$this->current_db_name])) { + if ($db_name == '') { + return count(Arr::dot($this->query_durations)); + } else if (!isset($this->query_durations[$db_name])) { return 0; } - return sizeof($this->query_durations[$this->current_db_name]); + return count($this->query_durations[$db_name]); } diff --git a/src/DbFactory.php b/src/DbFactory.php index 55c2506..07e6afc 100644 --- a/src/DbFactory.php +++ b/src/DbFactory.php @@ -24,6 +24,8 @@ public static function create(array $array): Db $connections = []; + $current_db_name = null; + foreach ($array as $name => $db_config) { // Check valid adapter @@ -38,14 +40,11 @@ public static function create(array $array): Db $adapter = 'Bayfront\SimplePdo\Adapters\\' . $db_config['adapter']; - if (isset($db_config['default']) && true === $db_config['default'] && !isset($db)) { // If default database + if ($current_db_name === null) { // First listed connection - // Create connection + $current_db_name = $name; - /* - * @throws Bayfront\SimplePdo\Exceptions\ConfigurationException - * @throws Bayfront\SimplePdo\Exceptions\UnableToConnectException - */ + // Create connection $pdo = $adapter::connect($db_config); @@ -57,30 +56,18 @@ public static function create(array $array): Db // Create connection - /* - * @throws Bayfront\SimplePdo\Exceptions\PdoException - */ - $connections[$name] = $adapter::connect($db_config); } } - if (!isset($db)) { // If default database does not exist - - throw new ConfigurationException('Invalid database configuration: no default database specified'); - + if (!isset($db)) { // If no databases were listed + throw new ConfigurationException('Invalid database configuration: no database specified'); } foreach ($connections as $name => $pdo) { - - /* - * @throws Bayfront\SimplePdo\Exceptions\InvalidDatabaseException - */ - $db->addConnection($pdo, $name); // Add all additional connections - } return $db;