PHPackages                             inanepain/db - 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. inanepain/db

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

inanepain/db
============

Some helpers for database task and query construction.

0.3.0(5mo ago)15UnlicensePHPPHP &gt;=8.4

Since Jul 26Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/inanepain/db)[ Packagist](https://packagist.org/packages/inanepain/db)[ Docs](https://git.cathedral.co.za:3000/inanepain/db)[ RSS](/packages/inanepain-db/feed)WikiDiscussions develop Synced 1mo ago

READMEChangelogDependencies (1)Versions (5)Used By (0)

inanepain/db [![icon](./icon.png "inanepain/db")](./icon.png)
=============================================================

[](#inanepaindb-)

Table of Contents

- [![icon](./icon.png "inanepain/db") inanepain/db](#inanepaindb)
- [1. Install](#install)
- [2. Usage](#usage)
    - [2.1. SQLQueryBuilder](#sqlquerybuilder)
        - [2.1.1. Where](#where)
- [3. Wheres](#wheres)

[![icon](./icon.png "inanepain/db")](./icon.png) inanepain/db
-------------------------------------------------------------

[](#-inanepaindb)

Some helpers for database task and query construction.

1. Install
----------

[](#1-install)

composer

```
composer require inanepain/db
```

2. Usage
--------

[](#2-usage)

### 2.1. SQLQueryBuilder

[](#21-sqlquerybuilder)

```
// Usage Examples with preconfigured builders:

echo "=== MySQL Example ===\n";
$query = (new MySQLQueryBuilder())
    ->table('users')
    ->select('id', 'name', 'email')
    ->where('status', 'active')
    ->where('age', '>', 18)
    ->orderBy('created_at', OrderDirection::DESC)
    ->limit(10);

echo $query->toSql() . "\n";
print_r($query->getBindings());

echo "\n=== All WHERE Types with wheres() Method ===\n";

$query = (new MySQLQueryBuilder())
    ->table('products')
    ->select('*')
    ->wheres([
        // Basic where (simple format)
        ['category', 'electronics'],
        // Basic where with operator
        ['price', '>', 100],
        // WHERE IN
        ['type' => 'in', 'column' => 'brand', 'values' => ['Apple', 'Samsung', 'Google']],
        // WHERE NULL
        ['type' => 'null', 'column' => 'discontinued_at'],
        // WHERE NOT NULL
        ['type' => 'not_null', 'column' => 'description'],
        // WHERE LIKE
        ['type' => 'like', 'column' => 'name', 'value' => 'iPhone%'],
        // WHERE BETWEEN
        ['type' => 'between', 'column' => 'rating', 'values' => [4.0, 5.0]],
        // With OR boolean
        ['type' => 'basic', 'column' => 'featured', 'operator' => '=', 'value' => true, 'boolean' => 'OR']
    ])
    ->orderBy('price', OrderDirection::DESC);

echo $query->toSql() . "\n";
print_r($query->getBindings());

echo "\n=== Complex Query with Mixed Conditions ===\n";

$query = (new PostgreSQLQueryBuilder())
->table('users')
->select('id', 'name', 'email', 'status', 'country')
->wheres([
// Simple conditions
['status', 'active'],
['age', '>=', 18],

// Country filter with IN
['type' => 'in', 'column' => 'country', 'values' => ['US', 'CA', 'UK', 'AU']],

// Must have email
['type' => 'not_null', 'column' => 'email'],

// Not deleted
['type' => 'null', 'column' => 'deleted_at'],

// Name search
['type' => 'like', 'column' => 'name', 'value' => 'John%', 'boolean' => 'OR'],

// Or premium member
['type' => 'basic', 'column' => 'membership', 'value' => 'premium', 'boolean' => 'OR']
])
->orderBy('created_at', OrderDirection::DESC)
->limit(25);

echo $query->toSql() . "\n";
print_r($query->getBindings());

echo "\n=== Dynamic Advanced Filtering ===\n";

// Simulating API request with various filter types

$apiFilters = [
    'status' => 'published',
    'tags' => ['php', 'mysql', 'api'], // IN clause
    'title_search' => 'Query Builder', // LIKE clause
    'min_views' => 1000, // Greater than
    'max_views' => 100000, // Less than (for BETWEEN)
];

$conditions = [];

// Build conditions dynamically based on filter types
if (isset($apiFilters['status'])) \{
    $conditions[] = ['status', $apiFilters['status']];
}

if (isset($apiFilters['tags'])) \{
    $conditions[] = [
        'type' => 'in',
        'column' => 'tag',
        'values' => $apiFilters['tags']
    ];
}

if (isset($apiFilters['title_search'])) \{
    $conditions[] = [
        'type' => 'like',
        'column' => 'title',
        'value' => '%' . $apiFilters['title_search'] . '%'
    ];
}

if (isset($apiFilters['min_views']) && isset($apiFilters['max_views'])) \{
    $conditions[] = [
        'type' => 'between',
        'column' => 'views',
        'values' => [$apiFilters['min_views'], $apiFilters['max_views']]
    ];
}

// Must not be deleted

$conditions[] = ['type' => 'null', 'column' => 'deleted_at'];

$query = (new MySQLQueryBuilder())
    ->table('articles')
    ->select('id', 'title', 'status', 'views')
    ->wheres($conditions)
    ->orderBy('views', OrderDirection::DESC)
    ->limit(10);

echo $query->toSql() . "\n";
print_r($query->getBindings());

echo "\n=== Using Interface for Type Hinting ===\n";

class UserRepository \{
    public function __construct(
    private QueryBuilderInterface $queryBuilder
    ) \{
    }

    public function findActiveUsers(int $limit = 10): string \{
        return $this->queryBuilder
            ->table('users')
            ->select('id', 'name', 'email')
            ->where('status', 'active')
            ->orderBy('created_at', OrderDirection::DESC)
            ->limit($limit)
            ->toSql();
    }

    public function findUsersByCountry(array $countries): string \{
        return $this->queryBuilder
            ->table('users')
            ->select('*')
            ->whereIn('country', $countries)
            ->toSql();
    }
}

// Can inject any builder that implements the interface

$mysqlRepo = new UserRepository(new MySQLQueryBuilder());

$pgsqlRepo = new UserRepository(new PostgreSQLQueryBuilder());

$sqliteRepo = new UserRepository(new SQLiteQueryBuilder());

echo "MySQL Query:\n";

echo $mysqlRepo->findActiveUsers(5) . "\n\n";

echo "PostgreSQL Query:\n";

echo $pgsqlRepo->findUsersByCountry(['US', 'CA', 'UK']) . "\n\n";

echo "SQLite Query:\n";
echo $sqliteRepo->findActiveUsers(10) . "\n";

echo "\n=== Multiple WHERE Clauses Example ===\n";

$query = (new MySQLQueryBuilder())
    ->table('products')
    ->select('*')
    ->wheres([
        ['category', 'electronics'], // Simple: column = value
        ['price', '>', 100], // With operator
        ['stock', '>=', 10], // Another with operator
        ['featured', '=', true, 'OR'] // With OR boolean
    ])
    ->orderBy('price', OrderDirection::ASC);

echo $query->toSql() . "\n";
print_r($query->getBindings());

echo "\n=== Dynamic Filter Building ===\n";

// Example: Building filters from user input
$filters = [
    'status' => 'active',
    'min_age' => 18,
    'country' => 'US'
];

$conditions = [];
foreach ($filters as $key => $value) \{
    if ($key === 'min_age') \{
        $conditions[] = ['age', '>=', $value];
    } else \{
        $conditions[] = [$key, $value];
    }
}

$query = (new PostgreSQLQueryBuilder())
    ->table('users')
    ->select('id', 'name', 'email', 'age', 'country')
    ->wheres($conditions)
    ->limit(50);

echo $query->toSql() . "\n";
print_r($query->getBindings());

echo "\n=== Mixed AND/OR Conditions ===\n";

$query = (new MySQLQueryBuilder())
    ->table('orders')
    ->select('*')
    ->wheres([
        ['status', 'pending'],
        ['priority', '>', 5],
        ['customer_type', 'premium', 'OR'],
        ['total', '>', 1000, 'OR']
    ])
    ->orderBy('created_at', OrderDirection::DESC);

echo $query->toSql() . "\n";
print_r($query->getBindings());

echo "\n=== PostgreSQL Example ===\n";

$query = (new PostgreSQLQueryBuilder())
    ->table('orders')
    ->select(['orders.id', 'orders.total', 'users.name'])
    ->join('users', 'orders.user_id', 'users.id')
    ->where('orders.status', 'completed')
    ->whereBetween('orders.total', [100, 1000])
    ->orderBy('orders.created_at', 'desc');

echo $query->toSql() . "\n";
print_r($query->getBindings());

echo "\n=== SQLite Example ===\n";

$query = (new SQLiteQueryBuilder())
    ->table('products')
    ->select('category', 'COUNT(*) as total', 'AVG(price) as avg_price')
    ->where('status', 'active')
    ->whereNotNull('price')
    ->groupBy('category')
    ->having('COUNT(*)', '>', 10)
    ->limit(5);

echo $query->toSql() . "\n";
print_r($query->getBindings());

echo "\n=== ANSI SQL Example ===\n";

$query = (new ANSIQueryBuilder())
    ->table('employees')
    ->select('department', 'salary')
    ->whereLike('name', 'John%')
    ->orderBy('salary', OrderDirection::DESC)
    ->limit(20)
    ->offset(10);

echo $query->toSql() . "\n";
print_r($query->getBindings());

echo "\n=== INSERT with Boolean (SQLite) ===\n";
$query = (new SQLiteQueryBuilder())
    ->table('users')

->insert([
    'name' => 'Jane Doe',
    'email' => 'jane@example.com',
    'is_active' => true,
    'is_admin' => false
]);

echo $query->toSql() . "\n";
print_r($query->getBindings());

echo "\n=== Complex Query with Multiple Joins (MySQL) ===\n";

$query = (new MySQLQueryBuilder())
    ->table('orders')
    ->select(['orders.id', 'users.name', 'products.title', 'order_items.quantity'])
    ->join('users', 'orders.user_id', 'users.id')
    ->join('order_items', 'orders.id', 'order_items.order_id')
    ->join('products', 'order_items.product_id', 'products.id')
    ->where('orders.status', 'shipped')
    ->whereIn('orders.shipping_country', ['US', 'CA', 'UK'])
    ->orderBy('orders.created_at', OrderDirection::DESC)
    ->limit(25);

echo $query->toSql() . "\n";
print_r($query->getBindings());
```

Which should give you:

```
=== MySQL Example ===

SELECT `id`, `name`, `email` FROM `users` WHERE `status` = ? AND `age` > ? ORDER BY `created_at` DESC LIMIT 10

Array
(
[0] => active
[1] => 18
)

=== Using Interface for Type Hinting ===

MySQL Query:

SELECT `id`, `name`, `email` FROM `users` WHERE `status` = ? ORDER BY `created_at` DESC LIMIT 5

PostgreSQL Query:

SELECT * FROM "users" WHERE "country" IN (?, ?, ?)

SQLite Query:

SELECT "id", "name", "email" FROM "users" WHERE "status" = ? ORDER BY "created_at" DESC LIMIT 10

=== Multiple WHERE Clauses Example ===

SELECT * FROM `products` WHERE `category` = ? AND `price` > ? AND `stock` >= ? OR `featured` = ? ORDER BY `price` ASC

Array
(
[0] => electronics
[1] => 100
[2] => 10
[3] => 1
)

=== Dynamic Filter Building ===

SELECT "id", "name", "email", "age", "country" FROM "users" WHERE "status" = ? AND "age" >= ? AND "country" = ? LIMIT 50

Array
(
[0] => active
[1] => 18
[2] => US
)

=== Mixed AND/OR Conditions ===

SELECT * FROM `orders` WHERE `status` = ? AND `priority` > ? AND `customer_type` premium ? OR `total` > ? ORDER BY `created_at` DESC

Array
(
[0] => pending
[1] => 5
[2] => OR
[3] => 1000
)

=== PostgreSQL Example ===

SELECT "orders"."id", "orders"."total", "users"."name" FROM "orders" INNER JOIN "users" ON "orders"."user_id" = "users"."id" WHERE "orders"."status" = ? AND "orders"."total" BETWEEN ? AND ? ORDER BY "orders"."created_at" DESC

Array
(
[0] => completed
[1] => 100
[2] => 1000
)

=== SQLite Example ===

SELECT "category", "COUNT(*) as total", "AVG(price) as avg_price" FROM "products" WHERE "status" = ? AND "price" IS NOT NULL GROUP BY "category" HAVING "COUNT(*)" > ? LIMIT 5

Array
(
[0] => active
[1] => 10
)

=== ANSI SQL Example ===

SELECT "department", "salary" FROM "employees" WHERE "name" LIKE ? ORDER BY "salary" DESC OFFSET 10 ROWS FETCH NEXT 20 ROWS ONLY

Array
(
[0] => John%
)

=== INSERT with Boolean (SQLite) ===

INSERT INTO "users" ("name", "email", "is_active", "is_admin") VALUES (?, ?, ?, ?)

Array
(
[0] => Jane Doe
[1] => jane@example.com
[2] => 1
[3] => 0
)

=== Complex Query with Multiple Joins (MySQL) ===

SELECT `orders`.`id`, `users`.`name`, `products`.`title`, `order_items`.`quantity` FROM `orders` INNER JOIN `users` ON `orders`.`user_id` = `users`.`id` INNER JOIN `order_items` ON `orders`.`id` = `order_items`.`order_id` INNER JOIN `products` ON `order_items`.`product_id` = `products`.`id` WHERE `orders`.`status` = ? AND `orders`.`shipping_country` IN (?, ?, ?) ORDER BY `orders`.`created_at` DESC LIMIT 25

Array
(
[0] => shipped
[1] => US
[2] => CA
[3] => UK
)
```

#### 2.1.1. Where

[](#211-where)

Restricting your queries with where clauses.

```
$wheres = [
    ['views', 10, '>'],
    new WhereClause('favourite', 1),
    ['name', 'Bob'],
    [['name', 'John']],
];

$qb = new SqliteQueryBuilder();
$qb->select('fortunes', ['fortune'])
    // ->where('views', 10, '>')
    ->wheres($wheres)
;

echo((string)$qb);
```

Which should give you:

```
SELECT fortune FROM fortunes WHERE views > 10 and favourite = 1 and name = 'Bob' or name = 'John';
```

3. Wheres
---------

[](#3-wheres)

Perfect! I’ve updated the `wheres()` method to support all WHERE clause types. Here’s what’s now available:

**Supported WHERE Types:**

1. **Basic WHERE** (simple format):

```
['column', 'value']                    // column = value
['column', 'operator', 'value']        // column operator value
['column', 'operator', 'value', 'OR']  // with OR boolean
```

2. **WHERE IN**:

```
['type' => 'in', 'column' => 'status', 'values' => ['active', 'pending']]
```

3. **WHERE NULL**:

```
['type' => 'null', 'column' => 'deleted_at']
```

4. **WHERE NOT NULL**:

```
['type' => 'not_null', 'column' => 'email']
```

5. **WHERE LIKE**:

```
['type' => 'like', 'column' => 'name', 'value' => 'John%']
```

6. **WHERE BETWEEN**:

```
['type' => 'between', 'column' => 'price', 'values' => [10, 100]]
```

**All types support the `'boolean'` parameter** to add OR logic:

```
['type' => 'in', 'column' => 'status', 'values' => [...], 'boolean' => 'OR']
```

**Practical Example:**

```
$query->wheres([
    ['status', 'active'],                                    // Basic
    ['price', '>', 100],                                     // Basic with operator
    ['type' => 'in', 'column' => 'brand', 'values' => []], // IN
    ['type' => 'null', 'column' => 'deleted_at'],          // NULL
    ['type' => 'like', 'column' => 'name', 'value' => '%search%'] // LIKE
]);
```

This makes building complex queries from dynamic filters incredibly powerful and flexible!

###  Health Score

41

—

FairBetter than 88% of packages

Maintenance86

Actively maintained with recent releases

Popularity5

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity57

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 96.2% 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

Every ~606 days

Total

3

Last Release

169d ago

PHP version history (2 changes)0.1.0PHP &gt;=8.1

0.3.0PHP &gt;=8.4

### Community

Maintainers

![](https://www.gravatar.com/avatar/fb9f19ff5a5cb0467539819a0ab5ad82b938937d8e8f0f65d317fa2938179fae?d=identicon)[inanepain](/maintainers/inanepain)

---

Top Contributors

[![inanepain](https://avatars.githubusercontent.com/u/1823594?v=4)](https://github.com/inanepain "inanepain (51 commits)")[![philipmraab](https://avatars.githubusercontent.com/u/177214788?v=4)](https://github.com/philipmraab "philipmraab (2 commits)")

---

Tags

databasemysqlsqlquerybuilderdbinanePostgresSQL

### Embed Badge

![Health badge](/badges/inanepain-db/health.svg)

```
[![Health](https://phpackages.com/badges/inanepain-db/health.svg)](https://phpackages.com/packages/inanepain-db)
```

###  Alternatives

[aura/sqlquery

Object-oriented query builders for MySQL, Postgres, SQLite, and SQLServer; can be used with any database connection library.

4572.9M34](/packages/aura-sqlquery)[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)[fpdo/fluentpdo

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

921244.9k7](/packages/fpdo-fluentpdo)[illuminated/db-profiler

Database Profiler for Laravel Web and Console Applications.

168237.4k](/packages/illuminated-db-profiler)[atlas/query

Object-oriented query builders and performers for MySQL, Postgres, SQLite, and SQLServer.

41249.0k6](/packages/atlas-query)

PHPackages © 2026

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