From ce460740cda5111a395581ff2018e07a289c9a54 Mon Sep 17 00:00:00 2001 From: Juan Pablo Vial Date: Thu, 8 Sep 2022 18:11:36 -0400 Subject: [PATCH 1/5] Dependencies --- composer.json | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/composer.json b/composer.json index c94854f..e16a293 100644 --- a/composer.json +++ b/composer.json @@ -1,21 +1,15 @@ { "name": "provm/database", - "description": "Database loader for j4mie/paris", - "type": "library", - "require": { - "j4mie/paris": "^1.5" - }, - "license": "MIT", - "autoload": { - "psr-4": { - "ProVM\\Database\\": "src/", - "ProVM\\Common\\": "common/" - } + "type": "project", + "require-dev": { + "phpunit/phpunit": "^9.5", + "kint-php/kint": "^4.2" }, "authors": [ { "name": "Aldarien", "email": "aldarien85@gmail.com" } - ] + ], + "require": {} } From 5322d81e1b74c2918374ef4495555c48a3bfbb5b Mon Sep 17 00:00:00 2001 From: Juan Pablo Vial Date: Thu, 8 Sep 2022 18:11:46 -0400 Subject: [PATCH 2/5] Interfaces --- src/Concept/Database.php | 20 ++++++++++++++++++++ src/Concept/Database/Connection.php | 18 ++++++++++++++++++ src/Concept/Database/ResultSet.php | 13 +++++++++++++ src/Concept/Database/Transaction.php | 12 ++++++++++++ 4 files changed, 63 insertions(+) create mode 100644 src/Concept/Database.php create mode 100644 src/Concept/Database/Connection.php create mode 100644 src/Concept/Database/ResultSet.php create mode 100644 src/Concept/Database/Transaction.php diff --git a/src/Concept/Database.php b/src/Concept/Database.php new file mode 100644 index 0000000..0ed1e0d --- /dev/null +++ b/src/Concept/Database.php @@ -0,0 +1,20 @@ + Date: Thu, 8 Sep 2022 20:01:52 -0400 Subject: [PATCH 3/5] Abstract --- src/Alias/Database.php | 58 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 src/Alias/Database.php diff --git a/src/Alias/Database.php b/src/Alias/Database.php new file mode 100644 index 0000000..8ece3db --- /dev/null +++ b/src/Alias/Database.php @@ -0,0 +1,58 @@ +host = $host; + return $this; + } + public function getHost(): string + { + return $this->host; + } + protected int $port; + public function setPort(int $port): DatabaseInterface + { + $this->port = $port; + return $this; + } + public function getPort(): int + { + return $this->port; + } + protected string $name; + public function setName(string $name): DatabaseInterface + { + $this->name = $name; + return $this; + } + public function getName(): string + { + return $this->name; + } + protected string $username; + public function setUsername(string $username): DatabaseInterface + { + $this->username = $username; + return $this; + } + public function getUsername(): string + { + return $this->username; + } + protected string $password; + public function setPassword(string $password): DatabaseInterface + { + $this->password = $password; + return $this; + } + public function getPassword(): string + { + return $this->password; + } +} From 0df2e95e7fb4a694455920972fa1c83845af37b0 Mon Sep 17 00:00:00 2001 From: Juan Pablo Vial Date: Thu, 8 Sep 2022 20:02:05 -0400 Subject: [PATCH 4/5] Implementations --- src/Database/Connection.php | 75 ++++++++++++++++++++++++++++++++++++ src/Database/MySQL.php | 28 ++++++++++++++ src/Database/ResultSet.php | 44 +++++++++++++++++++++ src/Database/Transaction.php | 59 ++++++++++++++++++++++++++++ 4 files changed, 206 insertions(+) create mode 100644 src/Database/Connection.php create mode 100644 src/Database/MySQL.php create mode 100644 src/Database/ResultSet.php create mode 100644 src/Database/Transaction.php diff --git a/src/Database/Connection.php b/src/Database/Connection.php new file mode 100644 index 0000000..0e5c8f3 --- /dev/null +++ b/src/Database/Connection.php @@ -0,0 +1,75 @@ +setDatabase($database); + $this->connect(); + } + + protected Database $database; + public function setDatabase(Database $database): ConnectionInterface + { + $this->database = $database; + return $this; + } + public function getDatabase(): Database + { + return $this->database; + } + public function connect(): ConnectionInterface + { + if (!isset($this->pdo)) { + if ($this->getDatabase()->needsUser()) { + $pdo = new PDO($this->getDatabase()->getDSN(), $this->getDatabase()->getUsername(), $this->getDatabase()->getPassword()); + } else { + $pdo = new PDO($this->getDatabase()->getDSN()); + } + $this->setPDO($pdo); + } + return $this; + } + protected PDO $pdo; + public function setPDO(PDO $pdo): ConnectionInterface + { + $this->pdo = $pdo; + return $this; + } + public function getPDO(): PDO + { + return $this->pdo; + } + public function query(string $query): ResultSetInterface + { + $st = $this->getPDO()->query($query); + if (!$st) { + throw new PDOException("Could not run query {$query}"); + } + return new ResultSet($st); + } + public function prepare(string $query): ResultSetInterface + { + $st = $this->getPDO()->prepare($query); + if (!$st) { + throw new PDOException("Could not prepare query {$query}"); + } + return new ResultSet($st); + } + public function execute(string $query, array $values): ResultSetInterface + { + return $this->prepare($query)->execute($values); + } + public function transaction(): TransactionInterface + { + return new Transaction($this->getPDO()); + } +} diff --git a/src/Database/MySQL.php b/src/Database/MySQL.php new file mode 100644 index 0000000..9836747 --- /dev/null +++ b/src/Database/MySQL.php @@ -0,0 +1,28 @@ +getHost()}" + ]; + if (isset($this->port)) { + $arr []= "port={$this->getPort()}"; + } + $arr []= "dbname={$this->getName()}"; + + return implode(':', [ + 'mysql', + implode(';', $arr) + ]); + } +} diff --git a/src/Database/ResultSet.php b/src/Database/ResultSet.php new file mode 100644 index 0000000..c234bd5 --- /dev/null +++ b/src/Database/ResultSet.php @@ -0,0 +1,44 @@ +setStatement($statement); + } + + protected PDOStatement $statement; + public function setStatement(PDOStatement $statement): RSInterface + { + $this->statement = $statement; + return $this; + } + public function getStatement(): PDOStatement + { + return $this->statement; + } + + public function execute(array $values): RSInterface + { + $this->getStatement()->execute($values); + return $this; + } + + public function getAsArray(): array + { + return $this->getStatement()->fetchAll(PDO::FETCH_ASSOC); + } + public function getAsObject(): array + { + return $this->getStatement()->fetchAll(PDO::FETCH_OBJ); + } + public function getFirst(): mixed + { + return $this->getStatement()->fetch(PDO::FETCH_OBJ); + } +} diff --git a/src/Database/Transaction.php b/src/Database/Transaction.php new file mode 100644 index 0000000..7901640 --- /dev/null +++ b/src/Database/Transaction.php @@ -0,0 +1,59 @@ +setPDO($pdo); + } + + protected PDO $pdo; + public function setPDO(PDO $pdo): TransactionInterface + { + $this->pdo = $pdo; + return $this; + } + public function getPDO(): PDO + { + return $this->pdo; + } + public function begin(): TransactionInterface + { + $this->getPDO()->beginTransaction(); + return $this; + } + public function query(string $query): ResultSetInterface + { + $st = $this->getPDO()->query($query); + if (!$st) { + throw new PDOException("Could not run query {$query}"); + } + return new ResultSet($st); + } + public function prepare(string $query): ResultSetInterface + { + $st = $this->getPDO()->prepare($query); + if (!$st) { + throw new PDOException("Could not prepare query {$query}"); + } + return new ResultSet($st); + } + public function execute(string $query, array $values): ResultSetInterface + { + return $this->prepare($query)->execute($values); + } + public function commit(): void + { + $this->getPDO()->commit(); + } + public function rollBack(): void + { + $this->getPDO()->rollBack(); + } +} From 28e31de2a10feea30d2772e094c53030ab87fdf6 Mon Sep 17 00:00:00 2001 From: Juan Pablo Vial Date: Thu, 8 Sep 2022 20:02:11 -0400 Subject: [PATCH 5/5] Readme --- Readme.md | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 Readme.md diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..aab6d10 --- /dev/null +++ b/Readme.md @@ -0,0 +1,119 @@ +# Database + +Database Abstraction Layer + +## Requirements + ++ PHP 8+ ++ PDO + +### Recommended + ++ [`php-di/php-di`](https://packagist.org/packages/php-di/php-di) + +## Installation + +`composer.json` +``` +{ + ... + "repositories": [ + ... + { + "type": "git", + "path": "https://git.provm.cl/ProVM/database.git" + } + ... + ], + ... + "require": { + ... + "provm/database": "^2.0" + ... + }, + ... +} +``` + +## Usage + +For `MySQL`/`MariaDB` + +Without `DI` +``` +$database new MySQL(); +$database->setHost(); +$database->setPort(); // If diferent from 3306 +$database->setUsername(); +$database->setPassword(); + +$connection = new Connection($database); +``` +With `DI` +``` +$container->set(ProVM\Concept\Database::class, function(Psr\Container\ContainerInterface $container) { + $database = $container->get(ProVM\Database\MySQL::class); + $database->setHost(); + $database->setPort(); // If diferent from 3306 + $database->setUsername(); + $database->setPassword(); + return $database; +}); +$container->set(ProVM\Concept\Database\Connection::class, function(Psr\Container\ContainerInterface $container) { + return new ProVM\Database\Connection($container->get(ProVM\Concept\Database::class); +}); +``` + +Run query +``` +$rs = $connection->query(); +``` +Run prepared statement +``` +$rs = $connection->prepare()->execute(); +or +$rs = $connection->execute(, ); +``` +Get data from ResultSet +``` +$data = $rs->getAsArray(); +$data_objs = $rs->getAsObject(); +``` + +## Definitions + +### Database +Database configuration ++ `Database::host` Connection host name [`string`] ++ `Database::port` Connection port number [`int`] ++ `Database::name` Database name to connect [`string`] ++ `Database::username` Optional. The username to connect [`string`] ++ `Database::password` Optional. The password for the username [`string`] ++ `Database->getDsn()` get dsn string for PDO connection. [`string`] ++ `Database->needsUser()` If a user is needed for the connection. + +### Connection +Connection handling ++ `Connection::query` Query the database ++ `Connection::prepare` Prepare query statement ++ `Connection::execute` Prepare and execute a query statement ++ `Conneciton::transaction` Return a transaction + +### Transaction +Transaction ++ `Transaction::begin` Begin transaction ++ `Transaction::commit` Commit changes ++ `Transaction::rollBack` Roll back changes ++ `Transaction::query` Same as `Connection::query` ++ `Transaction::prepare` Same as `Connection::prepare` ++ `Transaction::execute` Same as `Connection::execute` + +### ResultSet +Result set to handle PDOStatement ++ `ResultSet::execute` Execute a prepared statement ++ `ResultSet::getAsArray` Return query results as array of associative arrays ++ `ResultSet::getAsObject` Return query results as array of objects ++ `ResultSet::getFirst` Return first result as object + +## TODO ++ Implement other database types. eg: PostgreSQL, SQLite