https://github.com/aportela/db-wrapper
Custom php (pdo) database wrapper
https://github.com/aportela/db-wrapper
composer-package database pdo php php8 sqlite3
Last synced: about 2 months ago
JSON representation
Custom php (pdo) database wrapper
- Host: GitHub
- URL: https://github.com/aportela/db-wrapper
- Owner: aportela
- License: agpl-3.0
- Created: 2020-02-15T18:16:11.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2025-11-29T23:42:59.000Z (7 months ago)
- Last Synced: 2025-12-02T04:34:36.267Z (7 months ago)
- Topics: composer-package, database, pdo, php, php8, sqlite3
- Language: PHP
- Homepage:
- Size: 122 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# db-wrapper
Custom php PDO database wrapper
## Requirements
- mininum php version 8.4
## Limitations
At this time only SQLite, MariaDB/MySQL, PostgreSQL adapters are supported.
# install
```Shell
composer require "aportela/db-wrapper"
```
# install / initializate (SQLite) database example
```php
array
(
// SQLite settings (filename & path)
"filename" => "test.db",
"path" => __DIR__ . DIRECTORY_SEPARATOR . "data" . DIRECTORY_SEPARATOR
// custom extra settings for other adapters (MariaDB/PostgreSQL)
/*
"host" => "127.0.0.1",
"port" = > 3306,
"username" => "foo",
"password" => "bar",
"db"=> "mydb"
*/
),
/* uncoment next setting & comment NullLogger constructor if you want file logs with (my) custom rotating handler*/
/*
"logger" => array
(
"name" => "test",
"filename" => "test-DEBUG.log",
"path" => __DIR__ . DIRECTORY_SEPARATOR . "data" . DIRECTORY_SEPARATOR . "logs" . DIRECTORY_SEPARATOR,
"level" => \Monolog\Logger::DEBUG
)
*/
);
// create database directory if not found
if (! file_exists($settings["database"]["path"]))
{
mkdir($settings["database"]["path"]);
}
/*
// uncoment this & comment NullLogger constructor if you want file logs with (my) custom rotating handler
// create log directory if not found
if (! file_exists($settings["logger"]["path"]))
{
mkdir($settings["logger"]["path"]);
}
// logger (monolog) definition
$logger = new \Monolog\Logger($settings["logger"]["name"]);
$logger->pushProcessor(new \Monolog\Processor\UidProcessor());
$handler = new \Monolog\Handler\RotatingFileHandler($settings["logger"]["path"] . $settings["logger"]["filename"], 0, $settings["logger"]["level"]);
$handler->setFilenameFormat('{date}/{filename}', \Monolog\Handler\RotatingFileHandler::FILE_PER_DAY);
$logger->pushHandler($handler);
*/
// null logger (monolog) definition
$logger = new \Psr\Log\NullLogger("");
// we are using PDO sqlite adapter
$adapter = new \aportela\DatabaseWrapper\Adapter\PDOSQLiteAdapter(
$settings["database"]["path"] . $settings["database"]["filename"],
// PDO options
[
// turn off persistent connections
\PDO::ATTR_PERSISTENT => false,
// enable exceptions
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
// emulate prepared statements
\PDO::ATTR_EMULATE_PREPARES => true,
// set default fetch mode to array
\PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
],
// optional flags, bitmask to set "PRAGMA journal_mode = WAL" && "PRAGMA foreign_keys = ON"
\aportela\DatabaseWrapper\Adapter\PDOSQLiteAdapter::FLAGS_PRAGMA_JOURNAL_WAL | \aportela\DatabaseWrapper\Adapter\PDOSQLiteAdapter::FLAGS_PRAGMA_FOREIGN_KEYS_ON
);
/*
// MariaDB adapter
$adapter = new \aportela\DatabaseWrapper\Adapter\PDOMariaDBAdapter(
$settings["database"]["host"],
$settings["database"]["port"],
$settings["database"]["db"],
$settings["database"]["username"],
$settings["database"]["password"],
// PDO options
[
// turn off persistent connections
\PDO::ATTR_PERSISTENT => false,
// enable exceptions
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
// emulate prepared statements
\PDO::ATTR_EMULATE_PREPARES => true,
// set default fetch mode to array
\PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
]
);
// PostgreSQL adapter
$adapter = new \aportela\DatabaseWrapper\Adapter\PDOPostgreSQLAdapter(
$settings["database"]["host"],
$settings["database"]["port"],
$settings["database"]["db"],
$settings["database"]["username"],
$settings["database"]["password"],
// PDO options
[
// turn off persistent connections
\PDO::ATTR_PERSISTENT => false,
// enable exceptions
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
// emulate prepared statements
\PDO::ATTR_EMULATE_PREPARES => true,
// set default fetch mode to array
\PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
]
);
*/
// main object
$db = new \aportela\DatabaseWrapper\DB
(
$adapter,
$logger
);
$success = true;
// check if the database is already installed (install scheme with version table already exists)
if (! $db->isSchemaInstalled())
{
if ($db->installSchema())
{
echo "Database install success" . PHP_EOL;
} else
{
echo sprintf("Database install error, check logs (at %s)%s", $settings["logger"]["path"], PHP_EOL);
$success = false;
}
} else
{
echo "Database already installed" . PHP_EOL;
}
if ($success)
{
$results = $db->query(" SELECT release_number, release_date FROM VERSION; ");
if (is_array($results) && count($results) == 1)
{
echo sprintf("Current version: %s (installed on: %s)%s", $results[0]->release_number, $results[0]->release_date, PHP_EOL);
}
else
{
echo "SQL error" . PHP_EOL;
}
}
?>
```
# upgrade (SQLite) schema & exec some queries
```php
array(
// SQLite settings (filename & path)
"filename" => "test.db",
"path" => __DIR__ . DIRECTORY_SEPARATOR . "data" . DIRECTORY_SEPARATOR,
"upgradeSchemaPath" => __DIR__ . DIRECTORY_SEPARATOR . "upgrade.sql"
// custom extra settings for other adapters (MariaDB/PostgreSQL)
/*
"host" => "127.0.0.1",
"port" = > 3306,
"username" => "foo",
"password" => "bar",
"db"=> "mydb"
*/
),
/* uncoment next setting & comment NullLogger constructor if you want file logs with (my) custom rotating handler*/
/*
"logger" => array
(
"name" => "test",
"filename" => "test-DEBUG.log",
"path" => __DIR__ . DIRECTORY_SEPARATOR . "data" . DIRECTORY_SEPARATOR . "logs" . DIRECTORY_SEPARATOR,
"level" => \Monolog\Logger::DEBUG
)
*/
);
// create database directory if not found
if (! file_exists($settings["database"]["path"])) {
mkdir($settings["database"]["path"]);
}
if (! file_exists($settings["database"]["upgradeSchemaPath"])) {
die(sprintf("Upgrade schema not found (at %s)%s", $settings["database"]["upgradeSchemaPath"], PHP_EOL));
}
/*
// uncoment this & comment NullLogger constructor if you want file logs with (my) custom rotating handler
// create log directory if not found
if (! file_exists($settings["logger"]["path"]))
{
mkdir($settings["logger"]["path"]);
}
// logger (monolog) definition
$logger = new \Monolog\Logger($settings["logger"]["name"]);
$logger->pushProcessor(new \Monolog\Processor\UidProcessor());
$handler = new \Monolog\Handler\RotatingFileHandler($settings["logger"]["path"] . $settings["logger"]["filename"], 0, $settings["logger"]["level"]);
$handler->setFilenameFormat('{date}/{filename}', \Monolog\Handler\RotatingFileHandler::FILE_PER_DAY);
$logger->pushHandler($handler);
*/
// null logger (monolog) definition
$logger = new \Psr\Log\NullLogger("");
// we are using PDO sqlite adapter, also set the upgrade scheme (point to a local file)
$adapter = new \aportela\DatabaseWrapper\Adapter\PDOSQLiteAdapter(
$settings["database"]["path"] . $settings["database"]["filename"],
// PDO options
[
// turn off persistent connections
\PDO::ATTR_PERSISTENT => false,
// enable exceptions
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
// emulate prepared statements
\PDO::ATTR_EMULATE_PREPARES => true,
// set default fetch mode to array
\PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
],
// optional flags, bitmask to set "PRAGMA journal_mode = WAL" && "PRAGMA foreign_keys = ON"
\aportela\DatabaseWrapper\Adapter\PDOSQLiteAdapter::FLAGS_PRAGMA_JOURNAL_WAL | \aportela\DatabaseWrapper\Adapter\PDOSQLiteAdapter::FLAGS_PRAGMA_FOREIGN_KEYS_ON,
// READ upgrade SQL schema file definition on next block of this README.md
$settings["database"]["upgradeSchemaPath"]
);
/*
// MariaDB adapter
$adapter = new \aportela\DatabaseWrapper\Adapter\PDOMariaDBAdapter(
$settings["database"]["host"],
$settings["database"]["port"],
$settings["database"]["db"],
$settings["database"]["username"],
$settings["database"]["password"],
// PDO options
[
// turn off persistent connections
\PDO::ATTR_PERSISTENT => false,
// enable exceptions
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
// emulate prepared statements
\PDO::ATTR_EMULATE_PREPARES => true,
// set default fetch mode to array
\PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
],
$settings["database"]["upgradeSchemaPath"]
);
// PostgreSQL adapter
$adapter = new \aportela\DatabaseWrapper\Adapter\PDOPostgreSQLAdapter(
$settings["database"]["host"],
$settings["database"]["port"],
$settings["database"]["db"],
$settings["database"]["username"],
$settings["database"]["password"],
// PDO options
[
// turn off persistent connections
\PDO::ATTR_PERSISTENT => false,
// enable exceptions
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
// emulate prepared statements
\PDO::ATTR_EMULATE_PREPARES => true,
// set default fetch mode to array
\PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
],
$settings["database"]["upgradeSchemaPath"]
);
*/
// main object
$db = new \aportela\DatabaseWrapper\DB(
$adapter,
$logger
);
// try to upgrade SQL schema to last version (making a backup before any modification, change parameter to false to skip creating the backup, NOT RECOMMENDED)
$currentVersion = $db->upgradeSchema(true);
if ($currentVersion !== -1) {
echo sprintf("Database upgrade success, current version: %s%s", $currentVersion, PHP_EOL);
$db->query(" CREATE TABLE IF NOT EXISTS MYTABLE (id INTEGER PRIMARY KEY, name VARCHAR(32)); ");
$db->query(
" INSERT INTO MYTABLE (id, name) VALUES (:id, :name) ON CONFLICT DO UPDATE SET name = :name; ",
[
new \aportela\DatabaseWrapper\Param\IntegerParam(":id", 1),
new \aportela\DatabaseWrapper\Param\StringParam(":name", "foobar-" . uniqid())
]
);
$results = $db->query(" SELECT id, name FROM MYTABLE ORDER BY id DESC LIMIT 1 ");
if (is_array($results) && count($results) == 1) {
echo sprintf("Last row was id: %s - name: %s%s", $results[0]->id, $results[0]->name, PHP_EOL);
} else {
echo sprintf("SQL error, check logs (at %s)%s", $settings["logger"]["path"], PHP_EOL);
}
// after query custom function example for "parsing" rows
$afterQueryFunction = function ($rows): void {
array_map(
function ($item) {
// duplicate name property into new customField
$item->customField = $item->name;
return ($item);
},
$rows
);
};
// use custom params && (optional) after query function
$results = $db->query(
" SELECT id, name FROM MYTABLE WHERE id > :id ORDER BY id DESC LIMIT 1 ",
[
new \aportela\DatabaseWrapper\Param\IntegerParam(":id", 0),
],
$afterQueryFunction
);
if (is_array($results) && count($results) == 1) {
echo sprintf("Last row was id: %s - name: %s - customField: $%s%s", $results[0]->id, $results[0]->name, $results[0]->customField, PHP_EOL);
} else {
echo sprintf("SQL error, check logs (at %s)%s", $settings["logger"]["path"], PHP_EOL);
}
} else {
echo sprintf("Database upgrade error, check logs (at %s)%s", $settings["logger"]["path"], PHP_EOL);
}
```
# upgrade SQL schema file definition example
defined on $settings block of previous example
```php
"upgradeSchemaPath" => __DIR__ . DIRECTORY_SEPARATOR . "upgrade.sql"
```
```php
array
(
" CREATE TABLE IF NOT EXISTS TABLEV1 (id INTEGER PRIMARY KEY); ",
" INSERT INTO TABLEV1 VALUES (1); "
),
2 => array
(
" CREATE TABLE IF NOT EXISTS TABLEV2 (id INTEGER PRIMARY KEY); ",
)
)
);
?>
```
