diff --git a/src/Configuration.php b/src/Configuration.php
index e214aa8..b562e7b 100644
--- a/src/Configuration.php
+++ b/src/Configuration.php
@@ -27,6 +27,9 @@ class Configuration
/** @var Mode|null The mode in which the library is operating (filled after first connection if not configured) */
public static ?Mode $mode = null;
+ /** @var PDO|null The PDO instance to use for database commands */
+ private static ?PDO $_pdo = null;
+
/**
* Retrieve a new connection to the database
*
@@ -35,21 +38,24 @@ class Configuration
*/
public static function dbConn(): PDO
{
- if (empty(self::$pdoDSN)) {
- throw new DocumentException('Please provide a data source name (DSN) before attempting data access');
- }
- $db = new PDO(self::$pdoDSN, $_ENV['PDO_DOC_USERNAME'] ?? self::$username,
- $_ENV['PDO_DOC_PASSWORD'] ?? self::$password, self::$options);
+ if (is_null(self::$_pdo)) {
+ if (empty(self::$pdoDSN)) {
+ throw new DocumentException('Please provide a data source name (DSN) before attempting data access');
+ }
+ self::$_pdo = new PDO(self::$pdoDSN, $_ENV['PDO_DOC_USERNAME'] ?? self::$username,
+ $_ENV['PDO_DOC_PASSWORD'] ?? self::$password, self::$options);
- if (is_null(self::$mode)) {
- $driver = $db->getAttribute(PDO::ATTR_DRIVER_NAME);
- self::$mode = match ($driver) {
- 'pgsql' => Mode::PgSQL,
- 'sqlite' => Mode::SQLite,
- default => throw new DocumentException(
- "Unsupported driver $driver: this library currently supports PostgreSQL and SQLite")
- };
+ if (is_null(self::$mode)) {
+ $driver = self::$_pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
+ self::$mode = match ($driver) {
+ 'pgsql' => Mode::PgSQL,
+ 'sqlite' => Mode::SQLite,
+ default => throw new DocumentException(
+ "Unsupported driver $driver: this library currently supports PostgreSQL and SQLite")
+ };
+ }
}
- return $db;
+
+ return self::$_pdo;
}
}
diff --git a/src/Count.php b/src/Count.php
index ca945b2..df91c72 100644
--- a/src/Count.php
+++ b/src/Count.php
@@ -3,7 +3,6 @@
namespace BitBadger\PDODocument;
use BitBadger\PDODocument\Mapper\CountMapper;
-use PDO;
/**
* Functions to count documents
@@ -14,13 +13,12 @@ class Count
* Count all documents in a table
*
* @param string $tableName The name of the table in which documents should be counted
- * @param PDO|null $pdo The database connection to use (optional; will obtain one if not provided)
* @return int The count of documents in the table
* @throws DocumentException If one is encountered
*/
- public static function all(string $tableName, ?PDO $pdo = null): int
+ public static function all(string $tableName): int
{
- return Custom::scalar(Query\Count::all($tableName), [], new CountMapper(), $pdo);
+ return Custom::scalar(Query\Count::all($tableName), [], new CountMapper());
}
/**
@@ -28,16 +26,14 @@ class Count
*
* @param string $tableName The name of the table in which documents should be counted
* @param array|Field[] $fields The field comparison to match
- * @param PDO|null $pdo The database connection to use (optional; will obtain one if not provided)
* @param string $conjunction How to handle multiple conditions (optional; defaults to `AND`)
* @return int The count of documents matching the field comparison
* @throws DocumentException If one is encountered
*/
- public static function byFields(string $tableName, array $fields, ?PDO $pdo = null,
- string $conjunction = 'AND'): int
+ public static function byFields(string $tableName, array $fields, string $conjunction = 'AND'): int
{
$namedFields = Parameters::nameFields($fields);
return Custom::scalar(Query\Count::byFields($tableName, $namedFields, $conjunction),
- Parameters::addFields($namedFields, []), new CountMapper(), $pdo);
+ Parameters::addFields($namedFields, []), new CountMapper());
}
}
diff --git a/src/Custom.php b/src/Custom.php
index fc1a068..5ba6663 100644
--- a/src/Custom.php
+++ b/src/Custom.php
@@ -16,14 +16,13 @@ class Custom
*
* @param string $query The query to be run
* @param array $parameters The parameters for the query
- * @param PDO $pdo The database connection on which the query should be run
* @return PDOStatement The result of executing the query
* @throws DocumentException If the query execution is unsuccessful
*/
- public static function runQuery(string $query, array $parameters, PDO $pdo): PDOStatement
+ public static function &runQuery(string $query, array $parameters): PDOStatement
{
$debug = defined('PDO_DOC_DEBUG_SQL');
- $stmt = $pdo->prepare($query);
+ $stmt = Configuration::dbConn()->prepare($query);
foreach ($parameters as $key => $value) {
if ($debug) echo "
Binding $value to $key\n
";
$dataType = match (true) {
@@ -77,19 +76,16 @@ class Custom
* @param string $query The query to be executed (will have "LIMIT 1" appended)
* @param array $parameters Parameters to use in executing the query
* @param Mapper $mapper Mapper to deserialize the result
- * @param PDO|null $pdo The database connection to use (optional; will obtain one if not provided)
* @return false|TDoc The item if it is found, false if not
* @throws DocumentException If any is encountered
*/
- public static function single(string $query, array $parameters, Mapper $mapper, ?PDO $pdo = null): mixed
+ public static function single(string $query, array $parameters, Mapper $mapper): mixed
{
try {
- $stmt = self::runQuery("$query LIMIT 1", $parameters,
- is_null($pdo) ? $actualPDO = Configuration::dbConn() : $pdo);
+ $stmt = &self::runQuery("$query LIMIT 1", $parameters);
return ($first = $stmt->fetch(PDO::FETCH_ASSOC)) ? $mapper->map($first) : false;
} finally {
$stmt = null;
- if (isset($actualPDO)) $actualPDO = null;
}
}
@@ -98,16 +94,14 @@ class Custom
*
* @param string $query The query to execute
* @param array $parameters Parameters to use in executing the query
- * @param PDO|null $pdo The database connection to use (optional; will obtain one if not provided)
* @throws DocumentException If any is encountered
*/
- public static function nonQuery(string $query, array $parameters, ?PDO $pdo = null): void
+ public static function nonQuery(string $query, array $parameters): void
{
try {
- $stmt = self::runQuery($query, $parameters, is_null($pdo) ? $actualPDO = Configuration::dbConn() : $pdo);
+ $stmt = &self::runQuery($query, $parameters);
} finally {
$stmt = null;
- if (isset($actualPDO)) $actualPDO = null;
}
}
@@ -118,18 +112,16 @@ class Custom
* @param string $query The query to retrieve the value
* @param array $parameters Parameters to use in executing the query
* @param Mapper $mapper The mapper to obtain the result
- * @param PDO|null $pdo The database connection to use (optional; will obtain one if not provided)
* @return mixed|false|T The scalar value if found, false if not
* @throws DocumentException If any is encountered
*/
public static function scalar(string $query, array $parameters, Mapper $mapper, ?PDO $pdo = null): mixed
{
try {
- $stmt = self::runQuery($query, $parameters, is_null($pdo) ? $actualPDO = Configuration::dbConn() : $pdo);
+ $stmt = &self::runQuery($query, $parameters);
return ($first = $stmt->fetch(PDO::FETCH_NUM)) ? $mapper->map($first) : false;
} finally {
$stmt = null;
- if (isset($actualPDO)) $actualPDO = null;
}
}
}
diff --git a/src/Definition.php b/src/Definition.php
index 85b0169..be87c3a 100644
--- a/src/Definition.php
+++ b/src/Definition.php
@@ -2,8 +2,6 @@
namespace BitBadger\PDODocument;
-use PDO;
-
/**
* Functions to create tables and indexes
*/
@@ -13,13 +11,12 @@ class Definition
* Ensure a document table exists
*
* @param string $name The name of the table to be created if it does not exist
- * @param PDO|null $pdo The database connection to use (optional; will obtain one if not provided)
* @throws DocumentException If any is encountered
*/
- public static function ensureTable(string $name, ?PDO $pdo = null): void
+ public static function ensureTable(string $name): void
{
- Custom::nonQuery(Query\Definition::ensureTable($name), [], $pdo);
- Custom::nonQuery(Query\Definition::ensureKey($name), [], $pdo);
+ Custom::nonQuery(Query\Definition::ensureTable($name), []);
+ Custom::nonQuery(Query\Definition::ensureKey($name), []);
}
/**
@@ -28,11 +25,10 @@ class Definition
* @param string $tableName The name of the table which should be indexed
* @param string $indexName The name of the index
* @param array $fields Fields which should be a part of this index
- * @param PDO|null $pdo The database connection to use (optional; will obtain one if not provided)
* @throws DocumentException If any is encountered
*/
- public static function ensureFieldIndex(string $tableName, string $indexName, array $fields, ?PDO $pdo = null): void
+ public static function ensureFieldIndex(string $tableName, string $indexName, array $fields): void
{
- Custom::nonQuery(Query\Definition::ensureIndexOn($tableName, $indexName, $fields), [], $pdo);
+ Custom::nonQuery(Query\Definition::ensureIndexOn($tableName, $indexName, $fields), []);
}
}
diff --git a/src/Delete.php b/src/Delete.php
index 477bb26..00a408f 100644
--- a/src/Delete.php
+++ b/src/Delete.php
@@ -2,8 +2,6 @@
namespace BitBadger\PDODocument;
-use PDO;
-
/**
* Functions to delete documents
*/
@@ -14,12 +12,11 @@ class Delete
*
* @param string $tableName The table from which the document should be deleted
* @param mixed $docId The ID of the document to be deleted
- * @param PDO|null $pdo The database connection to use (optional; will obtain one if not provided)
* @throws DocumentException If any is encountered
*/
- public static function byId(string $tableName, mixed $docId, ?PDO $pdo = null): void
+ public static function byId(string $tableName, mixed $docId): void
{
- Custom::nonQuery(Query\Delete::byId($tableName), Parameters::id($docId), $pdo);
+ Custom::nonQuery(Query\Delete::byId($tableName), Parameters::id($docId));
}
/**
@@ -27,15 +24,13 @@ class Delete
*
* @param string $tableName The table from which documents should be deleted
* @param array|Field[] $fields The field comparison to match
- * @param PDO|null $pdo The database connection to use (optional; will obtain one if not provided)
* @param string $conjunction How to handle multiple conditions (optional; defaults to `AND`)
* @throws DocumentException If any is encountered
*/
- public static function byFields(string $tableName, array $fields, ?PDO $pdo = null,
- string $conjunction = 'AND'): void
+ public static function byFields(string $tableName, array $fields, string $conjunction = 'AND'): void
{
$namedFields = Parameters::nameFields($fields);
Custom::nonQuery(Query\Delete::byFields($tableName, $namedFields, $conjunction),
- Parameters::addFields($namedFields, []), $pdo);
+ Parameters::addFields($namedFields, []));
}
}
diff --git a/src/Document.php b/src/Document.php
index e6c209d..5f14323 100644
--- a/src/Document.php
+++ b/src/Document.php
@@ -2,8 +2,6 @@
namespace BitBadger\PDODocument;
-use PDO;
-
/**
* Functions that apply at a whole document level
*/
@@ -14,12 +12,11 @@ class Document
*
* @param string $tableName The name of the table into which the document should be inserted
* @param array|object $document The document to be inserted
- * @param PDO|null $pdo The database connection to use (optional; will obtain one if not provided)
* @throws DocumentException If any is encountered
*/
- public static function insert(string $tableName, array|object $document, ?PDO $pdo = null): void
+ public static function insert(string $tableName, array|object $document): void
{
- Custom::nonQuery(Query::insert($tableName), Parameters::json(':data', $document), $pdo);
+ Custom::nonQuery(Query::insert($tableName), Parameters::json(':data', $document));
}
/**
@@ -27,12 +24,11 @@ class Document
*
* @param string $tableName The name of the table to which the document should be saved
* @param array|object $document The document to be saved
- * @param PDO|null $pdo The database connection to use (optional; will obtain one if not provided)
* @throws DocumentException If any is encountered
*/
- public static function save(string $tableName, array|object $document, ?PDO $pdo = null): void
+ public static function save(string $tableName, array|object $document): void
{
- Custom::nonQuery(Query::save($tableName), Parameters::json(':data', $document), $pdo);
+ Custom::nonQuery(Query::save($tableName), Parameters::json(':data', $document));
}
/**
@@ -41,12 +37,11 @@ class Document
* @param string $tableName The table in which the document should be updated
* @param mixed $docId The ID of the document to be updated
* @param array|object $document The document to be updated
- * @param PDO|null $pdo The database connection to use (optional; will obtain one if not provided)
* @throws DocumentException If any is encountered
*/
- public static function update(string $tableName, mixed $docId, array|object $document, ?PDO $pdo = null): void
+ public static function update(string $tableName, mixed $docId, array|object $document): void
{
Custom::nonQuery(Query::update($tableName),
- array_merge(Parameters::id($docId), Parameters::json(':data', $document)), $pdo);
+ array_merge(Parameters::id($docId), Parameters::json(':data', $document)));
}
}
diff --git a/src/DocumentList.php b/src/DocumentList.php
index 60a7658..44ec060 100644
--- a/src/DocumentList.php
+++ b/src/DocumentList.php
@@ -18,11 +18,10 @@ class DocumentList
/**
* Constructor
*
- * @param PDO|null $pdo The database connection against which the query was opened
* @param PDOStatement|null $result The result of the query
* @param Mapper $mapper The mapper to deserialize JSON
*/
- private function __construct(private ?PDO $pdo, private ?PDOStatement $result, private Mapper $mapper) { }
+ private function __construct(private ?PDOStatement &$result, private readonly Mapper $mapper) { }
/**
* Construct a new document list
@@ -35,8 +34,8 @@ class DocumentList
*/
public static function create(string $query, array $parameters, Mapper $mapper): static
{
- $pdo = Configuration::dbConn();
- return new static($pdo, Custom::runQuery($query, $parameters, $pdo), $mapper);
+ $stmt = &Custom::runQuery($query, $parameters);
+ return new static($stmt, $mapper);
}
/**
@@ -50,6 +49,5 @@ class DocumentList
while ($row = $this->result->fetch(PDO::FETCH_ASSOC)) yield $this->mapper->map($row);
}
$this->result = null;
- $this->pdo = null;
}
}
diff --git a/src/Exists.php b/src/Exists.php
index 5b4e6cd..11548d4 100644
--- a/src/Exists.php
+++ b/src/Exists.php
@@ -3,7 +3,6 @@
namespace BitBadger\PDODocument;
use BitBadger\PDODocument\Mapper\ExistsMapper;
-use PDO;
/**
* Functions to determine if documents exist
@@ -15,13 +14,12 @@ class Exists
*
* @param string $tableName The name of the table in which document existence should be determined
* @param mixed $docId The ID of the document whose existence should be determined
- * @param PDO|null $pdo The database connection to use (optional; will obtain one if not provided)
* @return bool True if the document exists, false if not
* @throws DocumentException If any is encountered
*/
- public static function byId(string $tableName, mixed $docId, ?PDO $pdo = null): bool
+ public static function byId(string $tableName, mixed $docId): bool
{
- return Custom::scalar(Query\Exists::byId($tableName), Parameters::id($docId), new ExistsMapper(), $pdo);
+ return Custom::scalar(Query\Exists::byId($tableName), Parameters::id($docId), new ExistsMapper());
}
/**
@@ -29,16 +27,14 @@ class Exists
*
* @param string $tableName The name of the table in which document existence should be determined
* @param Field[] $fields The field comparison to match
- * @param PDO|null $pdo The database connection to use (optional; will obtain one if not provided)
* @param string $conjunction How to handle multiple conditions (optional; defaults to `AND`)
* @return bool True if any documents match the field comparison, false if not
* @throws DocumentException If any is encountered
*/
- public static function byFields(string $tableName, array $fields, ?PDO $pdo = null,
- string $conjunction = 'AND'): bool
+ public static function byFields(string $tableName, array $fields, string $conjunction = 'AND'): bool
{
$namedFields = Parameters::nameFields($fields);
return Custom::scalar(Query\Exists::byFields($tableName, $namedFields, $conjunction),
- Parameters::addFields($namedFields, []), new ExistsMapper(), $pdo);
+ Parameters::addFields($namedFields, []), new ExistsMapper());
}
}
diff --git a/src/Patch.php b/src/Patch.php
index 9bbbaa9..98e5378 100644
--- a/src/Patch.php
+++ b/src/Patch.php
@@ -2,8 +2,6 @@
namespace BitBadger\PDODocument;
-use PDO;
-
/**
* Functions to patch (partially update) documents
*/
@@ -15,13 +13,12 @@ class Patch
* @param string $tableName The table in which the document should be patched
* @param mixed $docId The ID of the document to be patched
* @param array|object $patch The object with which the document should be patched (will be JSON-encoded)
- * @param PDO|null $pdo The database connection to use (optional; will obtain one if not provided)
* @throws DocumentException If any is encountered (database mode must be set)
*/
- public static function byId(string $tableName, mixed $docId, array|object $patch, ?PDO $pdo = null): void
+ public static function byId(string $tableName, mixed $docId, array|object $patch): void
{
Custom::nonQuery(Query\Patch::byId($tableName),
- array_merge(Parameters::id($docId), Parameters::json(':data', $patch)), $pdo);
+ array_merge(Parameters::id($docId), Parameters::json(':data', $patch)));
}
/**
@@ -30,15 +27,14 @@ class Patch
* @param string $tableName The table in which documents should be patched
* @param array|Field[] $fields The field comparison to match
* @param array|object $patch The object with which the documents should be patched (will be JSON-encoded)
- * @param PDO|null $pdo The database connection to use (optional; will obtain one if not provided)
* @param string $conjunction How to handle multiple conditions (optional; defaults to `AND`)
* @throws DocumentException If any is encountered
*/
- public static function byFields(string $tableName, array $fields, array|object $patch, ?PDO $pdo = null,
+ public static function byFields(string $tableName, array $fields, array|object $patch,
string $conjunction = 'AND'): void
{
$namedFields = Parameters::nameFields($fields);
Custom::nonQuery(Query\Patch::byFields($tableName, $namedFields, $conjunction),
- Parameters::addFields($namedFields, Parameters::json(':data', $patch)), $pdo);
+ Parameters::addFields($namedFields, Parameters::json(':data', $patch)));
}
}
diff --git a/src/RemoveFields.php b/src/RemoveFields.php
index 4432c0f..b32e2f4 100644
--- a/src/RemoveFields.php
+++ b/src/RemoveFields.php
@@ -2,8 +2,6 @@
namespace BitBadger\PDODocument;
-use PDO;
-
/**
* Functions to remove fields from documents
*/
@@ -15,14 +13,13 @@ class RemoveFields
* @param string $tableName The table in which the document should have fields removed
* @param mixed $docId The ID of the document from which fields should be removed
* @param array|string[] $fieldNames The names of the fields to be removed
- * @param PDO|null $pdo The database connection to use (optional; will obtain one if not provided)
* @throws DocumentException If any is encountered
*/
- public static function byId(string $tableName, mixed $docId, array $fieldNames, ?PDO $pdo = null): void
+ public static function byId(string $tableName, mixed $docId, array $fieldNames): void
{
$nameParams = Parameters::fieldNames(':name', $fieldNames);
Custom::nonQuery(Query\RemoveFields::byId($tableName, $nameParams),
- array_merge(Parameters::id($docId), $nameParams), $pdo);
+ array_merge(Parameters::id($docId), $nameParams));
}
/**
@@ -31,16 +28,15 @@ class RemoveFields
* @param string $tableName The table in which documents should have fields removed
* @param array|Field[] $fields The field comparison to match
* @param array|string[] $fieldNames The names of the fields to be removed
- * @param PDO|null $pdo The database connection to use (optional; will obtain one if not provided)
* @param string $conjunction How to handle multiple conditions (optional; defaults to `AND`)
* @throws DocumentException If any is encountered
*/
- public static function byFields(string $tableName, array $fields, array $fieldNames, ?PDO $pdo = null,
+ public static function byFields(string $tableName, array $fields, array $fieldNames,
string $conjunction = 'AND'): void
{
$nameParams = Parameters::fieldNames(':name', $fieldNames);
$namedFields = Parameters::nameFields($fields);
Custom::nonQuery(Query\RemoveFields::byFields($tableName, $namedFields, $nameParams, $conjunction),
- Parameters::addFields($namedFields, $nameParams), $pdo);
+ Parameters::addFields($namedFields, $nameParams));
}
}