diff --git a/README.md b/README.md new file mode 100644 index 0000000..bfeb3fe --- /dev/null +++ b/README.md @@ -0,0 +1,52 @@ +# minphp/Db + +[![Build Status](https://travis-ci.org/phillipsdata/minphp-db.svg?banch=master)](https://travis-ci.org/phillipsdata/minphp-db) [![Coverage Status](https://coveralls.io/repos/phillipsdata/minphp-db/badge.svg)](https://coveralls.io/r/phillipsdata/minphp-db) + +Database Connection Library. + +Efficiently manages a connection, preventing a new one from being established if a matching connection already exists. + +## Installation + +Install via composer: + +```sh +composer require minphp/db:dev-master +``` + +## Basic Usage + +```php +use minphp\Db\PdoConnection; + +$dbInfo = array( + 'driver' => 'mysql', + 'host' => 'localhost', + 'database' => 'databasename', + 'user' => 'user', + 'pass' => 'pass' +); + +$connection = new PdoConnection($dbInfo); +$connection->query('SELECT * FROM table WHERE id=?', 1); +``` + +### Explicitly Connecting + +By default, PdoConnection will only connect to the database when a connection is required. To explicitly connect to the database use `connect()`: + +```php +use minphp\Db\PdoConnection; + +$dbInfo = array( + 'driver' => 'mysql', + 'host' => 'localhost', + 'database' => 'databasename', + 'user' => 'user', + 'pass' => 'pass' +); + +$connection = new PdoConnection($dbInfo); +$connection->connect(); +// Connection now ready and waiting +``` diff --git a/src/PdoConnection.php b/src/PdoConnection.php index c7f7857..24d9a72 100644 --- a/src/PdoConnection.php +++ b/src/PdoConnection.php @@ -3,7 +3,6 @@ use PDO; use PDOStatement; -use PDOException; use RuntimeException; use InvalidArgumentException; @@ -63,14 +62,22 @@ class PdoConnection * the given database info, or the default configured info set in the database * config file if no info is given * - * @param array $dbInfo Database information for this connection + * @param array $dbInfo Database information for this connection: + * - driver DB Driver + * - host DB Host + * - database DB name + * - user DB User + * - pass DB Password + * - port DB Port + * - options Array of PDO connection options */ - public function __construct(array $dbInfo = null) { + public function __construct(array $dbInfo) + { $this->dbInfo = $dbInfo; } /** - * Attemps to initialize a connection to the database if one does not already exist. + * Attemps to initialize a connection to the database if one does not already exist * * @return PDO The PDO connection */ @@ -80,16 +87,49 @@ public function connect() if ($connection instanceof PDO) { return $connection; } - return $this->makeConnection($this->dbInfo); + + // Attempt to reuse an existing connection if one exists that matches this connection + if ($this->reuseConnection + && ($key = array_search($this->dbInfo, self::$dbInfos)) !== false + ) { + $connection = self::$connections[$key]; + $this->setConnection($connection); + return $connection; + } + + $dsn = $this->makeDsn($this->dbInfo); + $username = isset($this->dbInfo['user']) + ? $this->dbInfo['user'] + : null; + $password = isset($this->dbInfo['pass']) + ? $this->dbInfo['pass'] + : null; + $options = (array) ( + isset($this->dbInfo['options']) + ? $this->dbInfo['options'] + : null + ) + + $this->options; + + $connection = $this->makeConnection($dsn, $username, $password, $options); + + self::$connections[] = $connection; + self::$dbInfos[] = $this->dbInfo; + $this->setConnection($connection); + + return $connection; } /** + * Set whether or not to reuse an existing connection * * @param boolean $enable True to reuse an existing matching connection if available + * @return PdoConnection */ public function reuseConnection($enable) { $this->reuseConnection = $enable; + return $this; } /** @@ -120,10 +160,12 @@ public function lastInsertId($name = null) * * @param long $attribute The attribute to set * @param int $value The value to assign to the attribute + * @return PdoConnection */ public function setAttribute($attribute, $value) { $this->connect()->setAttribute($attribute, $value); + return $this; } /** @@ -223,20 +265,12 @@ public function getConnection() * Set the PDO connection to use * * @param PDO $connection + * @return PdoConnection */ public function setConnection(PDO $connection) { $this->connection = $connection; - } - - /** - * Return all registered connections available - * - * @return array - */ - public function getRegisteredConnections() - { - return $this->connections; + return $this; } /** @@ -275,71 +309,23 @@ public function makeDsn(array $db) ); } - return $db['driver'] . ":dbname=" . $db['database'] . ";host=" . $db['host'] - . ( - isset($db['port']) - ? ";port=" . $db['port'] - : "" - ); + return isset($db['port']) + ? $db['driver'] . ':host=' . $db['host'] . ';dbname=' . $db['database'] . ';port=' . $db['port'] + : $db['driver'] . ':host=' . $db['host'] . ';dbname=' . $db['database']; } /** * Establish a new PDO connection using the given array of information. If * a connection already exists, no new connection will be created. * - * @param array $dbInfo Database information for this connection + * @param string $dsn + * @param string $username + * @param string $password + * @param array $options * @return \PDO The connection - * @throws RuntimeException Throw when PDOException is encountered */ - private function makeConnection(array $dbInfo) + private function makeConnection($dsn, $username, $password, $options) { - // Attempt to reuse an existing connection if one exists that matches this connection - if ($this->reuseConnection - && ($key = array_search($dbInfo, self::$dbInfos)) !== false - ) { - $this->setConnection(self::$connections[$key]); - return $this->getConnection(); - } - - // Override any default settings with those provided - $options = (array) ( - isset($dbInfo['options']) - ? $dbInfo['options'] - : null - ) - + $this->options; - - try { - $this->setConnection(new PDO( - $this->makeDsn($dbInfo), - ( - isset($dbInfo['user']) - ? $dbInfo['user'] - : null - ), - ( - isset($dbInfo['pass']) - ? $dbInfo['pass'] - : null - ), - $options - )); - $connection = $this->getConnection(); - - // Record the connection - self::$connections[] = $connection; - self::$dbInfos[] = $dbInfo; - - // Run a character set query to override the database server's default character set - if (!empty($dbInfo['charset_query'])) { - $this->query($dbInfo['charset_query']); - } - return $connection; - - } catch (PDOException $e) { - throw new RuntimeException($e->getMessage()); - } - - throw new RuntimeException('Connection could not be established.'); + return new PDO($dsn, $username, $password, $options); } } diff --git a/src/SqliteConnection.php b/src/SqliteConnection.php new file mode 100644 index 0000000..2670f6c --- /dev/null +++ b/src/SqliteConnection.php @@ -0,0 +1,13 @@ + ':memory:' + ); + } + + /** + * @covers ::connect + * @covers ::__construct + * @covers ::setConnection + * @covers ::getConnection + * @covers \minphp\Db\SqliteConnection::makeDsn + * @covers ::makeConnection + * @covers ::query + * @covers ::prepare + */ + public function testConnect() + { + $connection = new SqliteConnection($this->getDbInfo()); + $this->assertInstanceOf('\PDO', $connection->connect()); + } + + /** + * @covers ::__construct + * @covers ::reuseConnection + * @covers ::getConnection + * @covers ::setConnection + * @covers ::connect + * @covers \minphp\Db\SqliteConnection::makeDsn + * @covers ::makeConnection + */ + public function testReuseConnection() + { + $dbInfo = $this->getDbInfo(); + + $connectionA = new SqliteConnection($dbInfo); + $pdoA = $connectionA->connect(); + + $connectionB = new SqliteConnection($dbInfo); + $pdoB = $connectionB->reuseConnection(true)->connect(); + + $connectionC = new SqliteConnection($dbInfo); + $pdoC = $connectionC->reuseConnection(false)->connect(); + + $this->assertSame($pdoA, $pdoB); + $this->assertNotSame($pdoA, $pdoC); + } + + /** + * @covers ::__construct + * @covers ::connect + * @covers ::getConnection + * @covers ::makeDsn + * @covers ::makeConnection + * @expectedException \RuntimeException + */ + public function testConnectException() + { + $dbInfo = array( + 'driver' => 'invalid', + 'host' => 'invalid', + 'database' => 'invalid', + 'charset_query' => "SET NAMES 'utf8'" + ); + + $connection = new PdoConnection($dbInfo); + $connection->connect(); + } +} diff --git a/tests/Unit/PdoConnectionTest.php b/tests/Unit/PdoConnectionTest.php index fe1a2d7..7b79cb4 100644 --- a/tests/Unit/PdoConnectionTest.php +++ b/tests/Unit/PdoConnectionTest.php @@ -11,7 +11,7 @@ class PdoConnectionTest extends PHPUnit_Framework_TestCase { public function setUp() { - $this->connection = new PdoConnection(); + $this->connection = new PdoConnection(array()); } /** @@ -211,7 +211,7 @@ public function testMakeDsn() 'host' => 'localhost', 'port' => '8889' ); - $expected = 'mysql:dbname=database;host=localhost;port=8889'; + $expected = 'mysql:host=localhost;dbname=database;port=8889'; $this->assertEquals($expected, $this->connection->makeDsn($info)); } @@ -225,4 +225,13 @@ public function testMakeDsnException() { $this->connection->makeDsn(array()); } + + /** + * @covers ::reuseConnection + * @covers ::__construct + */ + public function testReuseConnection() + { + $this->assertSame($this->connection->reuseConnection(true), $this->connection); + } } diff --git a/tests/Unit/SqliteConnectionTest.php b/tests/Unit/SqliteConnectionTest.php new file mode 100644 index 0000000..ff57c49 --- /dev/null +++ b/tests/Unit/SqliteConnectionTest.php @@ -0,0 +1,24 @@ +assertEquals( + 'sqlite::memory:', + $connection->makeDsn(array('driver' => 'sqlite', 'database' => ':memory:')) + ); + } +}