PHPackages                             a-le/microdbal - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. a-le/microdbal

ActiveLibrary[Database &amp; ORM](/categories/database)

a-le/microdbal
==============

A simple yet efficient DBAL for PHP, built on top of PDO. It provides a lightweight and easy-to-use API for database operations.

v1.0.0(1y ago)11MITPHPPHP &gt;=8.2

Since Apr 15Pushed 1y ago1 watchersCompare

[ Source](https://github.com/a-le/microDbal)[ Packagist](https://packagist.org/packages/a-le/microdbal)[ RSS](/packages/a-le-microdbal/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (1)Dependencies (1)Versions (2)Used By (0)

microDbal
=========

[](#microdbal)

**microDbal** is a minimal PHP database abstraction layer.
It wraps PDO to give you clean, safe, and simple database access.

🚀 Why microDbal?
----------------

[](#-why-microdbal)

- ✅ Micro by design – no ORM, no query builder, no dependencies, no annotations
- ✅ Just SQL in, data out – fetch results as arrays or objects
- ✅ Great for prototyping or learning SQL from a PHP-first perspective
- ✅ Write raw SQL your way – use named (:name) or positional (?) placeholders
- ✅ Run prepared statements and fetch results in a single step
- ✅ **Inspired by** the PDO article series from [PHP Delusions](https://phpdelusions.net/)

💬 If you like microDbal, leave a ⭐ on GitHub — it really helps!

Tested with those Databases
---------------------------

[](#tested-with-those-databases)

Firebird, MySQL / MariaDB, MS SQL Server, PostgreSQL, SQLite.
Should support any database that is compatible with PHP's PDO.

Installation
------------

[](#installation)

Install via Composer:

```
composer require a-le/microdbal
```

Or alternatively:
Simply drop MicroDbal.php into your project folder and include it manually.

Usage
-----

[](#usage)

**Note:** SQL must be adapted to your targeted database. The following examples use SQL syntax for **SQLite**.

### 1. Autoload with composer

[](#1-autoload-with-composer)

```
require __DIR__ . '/vendor/autoload.php'; // Include the Composer autoloader
use aLe\MicroDbal;
```

#### Or alternatively:

[](#or-alternatively)

```
require 'microdbal.php';
use aLe\MicroDbal;
```

### 2. Connect to the Database

[](#2-connect-to-the-database)

```
// Constructor signature: __construct(string $dsn, ?string $username = null, ?string $password = null)
$db = new MicroDbal('sqlite::memory:');
```

---

### 3. Run Queries

[](#3-run-queries)

```
// Method signature: run(string $sql, array $args = [], ?int &$affectedRows = null): PDOStatement
$db->run('CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR, age INTEGER)');
$db->run('INSERT INTO test (name, age) VALUES (?, ?)', ['Pauline', 25]); // question mark placeholder
$db->run('INSERT INTO test (name, age) VALUES (:name, :age)', ['name' => 'Ryan', 'age' => 15]); // named placeholder
```

---

### 4. Get All Rows

[](#4-get-all-rows)

```
// Method signature: getAll(string $sql, array $args = [], ?array &$columnsMeta = null): array
$rows = $db->getAll('SELECT * FROM test WHERE age > ?', [10]);
print_r($rows);
```

**Output:**

```
Array
(
    [0] => Array
        (
            [id] => 1
            [name] => Pauline
            [age] => 25
        ),
    [1] => Array
        (
            [id] => 2
            [name] => Ryan
            [age] => 15
        )
)
```

---

### 5. Get a Single Row

[](#5-get-a-single-row)

```
// Method signature: getRow(string $sql, array $args = [], ?array &$columnsMeta = null): array
$row = $db->getRow('SELECT * FROM test WHERE id = ?', [1]);
print_r($row);
```

**Output:**

```
Array
(
    [id] => 1
    [name] => Pauline
    [age] => 25
)
```

---

### 6. Get a Single Column

[](#6-get-a-single-column)

```
// Method signature: getCol(string $sql, array $args = []): array
$col = $db->getCol('SELECT id FROM test WHERE age >= ?', [10]);
print_r($col);
```

**Output:**

```
Array
(
    [0] => 1,
    [1] => 2,
)
```

---

### 7. Get a Single Value

[](#7-get-a-single-value)

```
// Method signature: getOne(string $sql, array $args = []): mixed
$cnt = $db->getOne('SELECT COUNT(*) FROM test WHERE age < ?', [18]);
print_r($cnt);
```

**Output:**

```
1
```

---

### 8. Get Affected Rows

[](#8-get-affected-rows)

```
$db->run('INSERT INTO test (name, age) VALUES (?, ?)', ['Marty', 65], $affectedRows);
print_r($affectedRows);
```

**Output:**

```
1
```

---

### 9. Get Last Inserted ID

[](#9-get-last-inserted-id)

```
print_r($db->getLastInsertedId());
```

**Output:**

```
3
```

---

### 10. Get Column Metadata

[](#10-get-column-metadata)

```
$db->getAll('SELECT * FROM test WHERE false', [], $columnsMeta);
print_r($columnsMeta);
```

**Output:**

```
Array
(
    [0] => Array
        (
            [name] => id
            (...)
        )
    [1] => Array
        (
            [name] => name
            (...)
        )
    [2] => Array
        (
            [name] => age
            (...)
        )
)
```

---

### 11. Transactions

[](#11-transactions)

```
$db->beginTransaction();
$db->run('INSERT INTO test (name, age) VALUES (?, ?)', ['John', 30]);
$db->commit();

$db->beginTransaction();
$db->run('INSERT INTO test (name, age) VALUES (?, ?)', ['Jane', 40]);
$db->rollBack();

if ($db->inTransaction()) {
    echo "Transaction is active.";
}
```

---

### 12. Fetch Objects

[](#12-fetch-objects)

```
class Person
{
    public int $id;
    public string $name;
    public int $age;
}

// Method signature: getOneObject(string $sql, array $args = [], string $className): ?object
$person = $db->getOneObject('SELECT * FROM test WHERE id = ?', [1], Person::class);

// Method signature: getAllObjects(string $sql, array $args = [], string $className): array
$peopleAbove18 = $db->getAllObjects('SELECT * FROM test where age > ?', [18], Person::class);
```

---

### 13. SQL `IN` Helper

[](#13-sql-in-helper)

```
// Method signature: sqlIn(array $values): string
$arr = [1, 2, 3];
$sqlFragment = $db->sqlIn($arr);
$result = $db->getAll('SELECT * FROM test WHERE id IN ' . $sqlFragment, $arr);
```

---

### 14. SQL `LIKE` Helper

[](#14-sql-like-helper)

```
// Method signature: sqlLike(string $value, string $escapeChar = '\\'): string
$s = 'P';
$arg = $db->sqlLike($s). '%';
$result = $db->getAll('SELECT * FROM test WHERE name LIKE ?', [$arg]);
```

---

### 15. Access the PDO Instance

[](#15-access-the-pdo-instance)

The underlying PDO instance is exposed as a public property: `$db->pdo`.
You can use it directly for uncovered operations or to integrate with other libraries that expect a PDO object.

For example, using [delight-im/PHP-Auth](https://github.com/delight-im/PHP-Auth), which requires a PDO connection:

```
$auth = new \Delight\Auth\Auth($db->pdo);
```

---

### 16. Access the PDO Statement Object

[](#16-access-the-pdo-statement-object)

The `run` method returns a standard PDOStatement object, which you can use as needed — for example, to manually fetch rows one by one:

```
$stmt = $db->run('SELECT * FROM test');
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
    // Do something with $row
}
```

This gives you full control over result fetching, especially useful for large datasets or custom processing.

---

FAQ
---

[](#faq)

### What happens if there is an error?

[](#what-happens-if-there-is-an-error)

- This library enforces `PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION`, which ensures that PDO will throw an exception (`PDOException`) whenever an error occurs.
- These exceptions can be handled like any other PHP error using `try...catch` blocks.

#### Common setups for dealing with PHP errors:

[](#common-setups-for-dealing-with-php-errors)

- **Development Environment:**

    - Display errors for debugging purposes.
    - Example configuration in `php.ini`: ```
        error_reporting = E_ALL
        display_errors = On
        ```
- **Production Environment:**

    - Log errors instead of displaying them to the user.
    - Example configuration in `php.ini`: ```
        error_reporting = E_ALL
        display_errors = Off
        log_errors = On
        error_log = /path/to/error.log
        ```

With these configurations:

- In development, errors will be displayed to help with debugging.
- In production, errors will be logged to a file to avoid exposing sensitive information to users.

If you need to recover from an error, you can use a `try...catch` block to handle the exception and continue the script's execution.

For more information about the rationale behind this approach, see: [PHP Delusions - Try Catch](https://phpdelusions.net/delusion/try-catch)

---

Running Tests
-------------

[](#running-tests)

To run tests using PHPUnit:

1. Clone the repository with composer :

    ```
    composer install a-le/microdbal
    ```
2. Run tests on SQLite (default to memory DB if no DSN provided) :

    ```
    php run-tests.php
    ```
3. Run tests on any database connection :

    ```
    php run-tests.php
    ```

    Example

    ```
    php run-tests.php "pgsql:dbname=postgres;host=localhost" "user" "password"
    ```

Status
------

[](#status)

First stable version just released (april, 2025).

🤝 Contributing
--------------

[](#-contributing)

Contributions are very welcome!
Feel free to open an issue for bug reports, feature requests, or questions.

> 🛠️ This library aims to remain **micro**.
> If you'd like to submit a pull request, please open an issue or discussion first to make sure it aligns with the project's goals.

License
-------

[](#license)

This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.

###  Health Score

28

—

LowBetter than 54% of packages

Maintenance47

Moderate activity, may be stable

Popularity3

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity49

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

398d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/5c4cfa3686d2b35a916ac21421026d830bd3f964f9fa489876d69d920e65d380?d=identicon)[a-le](/maintainers/a-le)

---

Top Contributors

[![a-le](https://avatars.githubusercontent.com/u/5058790?v=4)](https://github.com/a-le "a-le (19 commits)")

---

Tags

phpdatabasedbalpdo

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/a-le-microdbal/health.svg)

```
[![Health](https://phpackages.com/badges/a-le-microdbal/health.svg)](https://phpackages.com/packages/a-le-microdbal)
```

###  Alternatives

[envms/fluentpdo

FluentPDO is a quick and light PHP library for rapid query building. It features a smart join builder, which automatically creates table joins.

925511.7k13](/packages/envms-fluentpdo)[lichtner/fluentpdo

FluentPDO is a quick and light PHP library for rapid query building. It features a smart join builder, which automatically creates table joins.

921274.8k6](/packages/lichtner-fluentpdo)[clouddueling/mysqldump-php

PHP version of mysqldump cli that comes with MySQL

1.3k22.9k](/packages/clouddueling-mysqldump-php)[popphp/pop-db

Pop Db Component for Pop PHP Framework

1814.6k11](/packages/popphp-pop-db)[riverside/php-orm

PHP ORM micro-library and query builder

111.2k](/packages/riverside-php-orm)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
