maduser/argon-database

A PHP package for database interactions

1.0.0 2025-07-26 16:26 UTC

This package is auto-updated.

Last update: 2025-07-27 06:20:45 UTC


README

PHP Build codecov Psalm Level Code Style Latest Version License: MIT

Argon Database

DBAL wrapper built on top of PDO for PHP 8.2+.

Features

  • Not a ORM
  • PDO-based abstraction
  • Strict typing everywhere
  • DTO hydration
  • Supports MySQL, Postgres, SQLite

Installation

composer require maduser/argon-database

Creating a Client

Wrap your DB config in a LazyConnectionProvider, then pass to QueryClient.

use Maduser\Argon\Database\QueryClient;
use Maduser\Argon\Database\PDO\MySQL\MySQLConfig;
use Maduser\Argon\Database\PDO\LazyConnectionProvider;

$provider = new LazyConnectionProvider(
    new MySQLConfig('127.0.0.1', 3306, 'argondb', 'argon', 'secret')
);

$db = new QueryClient($provider);

Other drivers:

new PostgresConfig('127.0.0.1', 5432, 'argondb', 'argon', 'secret');
new SqliteConfig(__DIR__ . '/mydb.sqlite');

Query Usage

fetchAll()

$rows = $db
    ->query('SELECT * FROM users WHERE active = :active', ['active' => true])
    ->fetchAll();

Returns: list<array<string, scalar|null>>

fetchOne()

$user = $db
    ->query('SELECT * FROM users WHERE id = :id', ['id' => 42])
    ->fetchOne();

Returns: array<string, scalar|null> | null

execute()

$db->query('UPDATE users SET banned = true WHERE id = :id', ['id' => 666])
   ->execute();

Returns: void

file()

$users = $db
    ->file(__DIR__ . '/queries/select_active_users.sql', ['limit' => 10])
    ->fetchAll();

Throws if the file is unreadable or empty.

Using DTOs with RowMapper

To hydrate rows into typed objects, implement RowMapper<T> on your DTO:

use Maduser\Argon\Database\Contracts\RowMapper;

/**
 * @implements RowMapper<User>
 */
final class User implements RowMapper
{
    public function __construct(
        public readonly int $id,
        public readonly string $email
    ) {}

    public static function map(array $row): self
    {
        return new self(
            id: (int) $row['id'],
            email: (string) $row['email']
        );
    }
}

Then hydrate:

/** @var list<User> */
$users = $db
    ->query('SELECT * FROM users')
    ->fetchAllTo(User::class);

/** @var User|null */
$user = $db
    ->query('SELECT * FROM users WHERE id = :id', ['id' => 1])
    ->fetchOneTo(User::class);

Transactions

$result = $db->transaction(function (QueryClient $trx) {
    $trx->query(...)->execute();
    return 'done';
});

Commits on success, rolls back on exception.

License

MIT.