PHPackages                             initorm/query-builder - 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. initorm/query-builder

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

initorm/query-builder
=====================

Lightweight, dialect-aware SQL query builder for PHP with parameterized output suitable for PDO.

2.0.0(2mo ago)0137[2 PRs](https://github.com/InitORM/QueryBuilder/pulls)1MITPHPPHP ^8.1CI passing

Since Dec 7Pushed 1mo agoCompare

[ Source](https://github.com/InitORM/QueryBuilder)[ Packagist](https://packagist.org/packages/initorm/query-builder)[ Docs](https://github.com/InitORM/QueryBuilder)[ GitHub Sponsors](https://github.com/muhammetsafak)[ RSS](/packages/initorm-query-builder/feed)WikiDiscussions master Synced 1w ago

READMEChangelog (3)Dependencies (4)Versions (11)Used By (1)

InitORM QueryBuilder
====================

[](#initorm-querybuilder)

[![Packagist Version](https://camo.githubusercontent.com/957e3fdb501d4fdc646963c879cc2090d0e99b7a709ce0560da070131e8085da/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f696e69746f726d2f71756572792d6275696c6465722e737667)](https://packagist.org/packages/initorm/query-builder)[![Total Downloads](https://camo.githubusercontent.com/65558f00e697715294b1dfaee00198176f9b57db9d8cf07898e6ea0228f0d50b/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f696e69746f726d2f71756572792d6275696c6465722e737667)](https://packagist.org/packages/initorm/query-builder)[![PHP Version](https://camo.githubusercontent.com/66fb901bdb85fc3d8c61efdf92d7dc6c2db666cb8cd8f5be51954264f82cf6aa/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f696e69746f726d2f71756572792d6275696c6465722e737667)](https://packagist.org/packages/initorm/query-builder)[![License](https://camo.githubusercontent.com/3208cad5c063d137497d7905de5094e203d05efe441743c200337a010a46c23e/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f696e69746f726d2f71756572792d6275696c6465722e737667)](LICENSE)[![PHPUnit](https://github.com/InitORM/QueryBuilder/actions/workflows/phpunit.yml/badge.svg)](https://github.com/InitORM/QueryBuilder/actions/workflows/phpunit.yml)[![PHPStan](https://github.com/InitORM/QueryBuilder/actions/workflows/phpstan.yml/badge.svg)](https://github.com/InitORM/QueryBuilder/actions/workflows/phpstan.yml)[![PHP_CodeSniffer](https://github.com/InitORM/QueryBuilder/actions/workflows/phpcs.yml/badge.svg)](https://github.com/InitORM/QueryBuilder/actions/workflows/phpcs.yml)

A lightweight, dialect-aware **SQL query builder** for PHP. It turns fluent calls into a SQL string plus a separate parameter bag suitable for direct execution with **PDO** — without ever concatenating user values into SQL.

InitORM QueryBuilder is the lowest layer of the [InitORM](https://github.com/InitORM)package family; it has **no runtime dependencies** beyond the `pdo` extension and is designed to be used either standalone or as part of the `initorm/database` and `initorm/orm` stack.

Why this library
----------------

[](#why-this-library)

- **Safe by default** — every value goes through a collision-safe parameter bag. Raw fragments are opt-in via `RawQuery`.
- **Dialect aware** — identifier escaping is delegated to pluggable drivers for MySQL/MariaDB, PostgreSQL, SQLite, plus a no-op generic driver.
- **Tiny and predictable** — single namespace, no service container, no reflection, no annotations; the whole thing is around 1 600 lines of code.
- **Battle-tested clause DSL** — comparison operators, BETWEEN, IN, LIKE family (`like` / `startLike` / `endLike`), NULL checks, REGEXP, SOUNDEX, FIND\_IN\_SET, sub-queries, parenthesized groups, closure-based JOIN ON expressions.

Requirements
------------

[](#requirements)

- **PHP ≥ 8.1**
- **`ext-pdo`** (only needed by the consumer at execution time; the builder itself does not require an open connection)

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

[](#installation)

```
composer require initorm/query-builder
```

Quick start
-----------

[](#quick-start)

```
use InitORM\QueryBuilder\QueryBuilder;

$qb = new QueryBuilder('mysql');

$sql = $qb
    ->select('u.id', 'u.name')
    ->from('users AS u')
    ->where('u.status', 1)
    ->andWhere('u.country', 'TR')
    ->orderBy('u.id', 'DESC')
    ->limit(20)
    ->generateSelectQuery();

// $sql ─────────────────────────────────────────────────────────────────
// SELECT `u`.`id`, `u`.`name`
//   FROM `users` AS `u`
//  WHERE `u`.`status` = 1 AND `u`.`country` = :country
//  ORDER BY `u`.`id` DESC
//  LIMIT 20

$pdo = new PDO('mysql:host=localhost;dbname=app', 'app', 'secret');
$stmt = $pdo->prepare($sql);
$stmt->execute($qb->getParameter()->all());
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
```

### INSERT

[](#insert)

```
$qb->from('users')->set([
    'name'    => 'Muhammet',
    'email'   => 'info@muhammetsafak.com.tr',
    'created' => $qb->raw('NOW()'),
]);

echo $qb->generateInsertQuery();
// INSERT INTO `users` (`name`, `email`, `created`)
//   VALUES (:name, :email, NOW());
```

### Sub-query in WHERE IN

[](#sub-query-in-where-in)

```
$qb->select('u.name')
   ->from('users AS u')
   ->whereIn('u.id', $qb->subQuery(function (QueryBuilder $sub) {
       $sub->select('id')->from('roles')->where('name', 'admin');
   }));
// SELECT `u`.`name` FROM `users` AS `u`
//  WHERE `u`.`id` IN (SELECT `id` FROM `roles` WHERE `name` = :name)
```

### Closure-based JOIN ON

[](#closure-based-join-on)

```
$qb->select('p.title', 'u.name')
   ->from('posts AS p')
   ->innerJoin('users AS u', function (QueryBuilder $j) {
       $j->on('u.id', 'p.user_id')
         ->where('u.active', 1);
   });
```

### Batch UPDATE (CASE/WHEN)

[](#batch-update-casewhen)

```
$qb->from('posts')
   ->set(['id' => 1, 'title' => 'First',  'views' => 100])
   ->set(['id' => 2, 'title' => 'Second', 'views' =>  42]);

echo $qb->generateUpdateBatchQuery('id');
// UPDATE `posts`
//    SET `title` = CASE WHEN `id` = 1 THEN :title WHEN `id` = 2 THEN :title_1 ELSE `title` END,
//        `views` = CASE WHEN `id` = 1 THEN 100   WHEN `id` = 2 THEN 42         ELSE `views` END
//  WHERE `id` IN (1, 2)
```

Supported drivers
-----------------

[](#supported-drivers)

StringDriver classEscape char`'mysql'``Drivers\MySqlDriver`````'pgsql'` / `'postgres'` / `'postgresql'``Drivers\PostgreSqlDriver``"``'sqlite'``Drivers\SqliteDriver`````null` (or anything unknown)`Drivers\GenericDriver` (no quoting)*(none)*A custom dialect can be added by extending `Drivers\AbstractDriver` and setting the `NAME` and `ESCAPE_CHAR` class constants.

Documentation
-------------

[](#documentation)

Full developer documentation with runnable examples lives in [`docs/`](docs/) — see [`docs/en/index.md`](docs/en/index.md) for the table of contents.

Security
--------

[](#security)

InitORM QueryBuilder is built around the rule **"user input is a value, never an identifier or a SQL fragment"**. Defenses shipped in 2.0.0:

- **Identifier hardening** — `escapeIdentifier()` rejects `;` and `--` so query-breakout characters in a column or table name cannot survive the escape pass (relevant especially on PostgreSQL, where PDO allows multi-statement queries by default).
- **LIKE wildcard auto-escape** — `%`, `_`, and `\` inside user-supplied LIKE values are escaped by default. Opt out with `$qb->raw(...)` when raw wildcards are intentional.
- **Strict placeholder regex** — placeholder names are now tightly bound to `^:\w+$`.
- **FIND\_IN\_SET parameter fix (B28)** — a pre-2.0.0 inversion bug inlined raw user strings as SQL; fixed.

The full threat model, residual application-level concerns (`ORDER BY` whitelisting, value-shaped function detection), and a complete regression suite live in [`docs/en/security.md`](docs/en/security.md) and [`tests/SecurityTest.php`](tests/SecurityTest.php).

Report vulnerabilities through the [organization-wide security policy](https://github.com/InitORM/.github/blob/main/SECURITY.md).

Tests, lint, static analysis
----------------------------

[](#tests-lint-static-analysis)

```
composer install
composer test     # phpunit (with pcov line-coverage summary)
composer cs       # PHP_CodeSniffer (PSR-12)
composer cs-fix   # phpcbf — auto-fix style violations
composer stan     # PHPStan level 6
composer qa       # cs-ci + stan + test
```

The repository ships with GitHub Actions workflows under [`.github/workflows/`](.github/workflows) that run the same checks on every push and pull request, across the PHP 8.1 → 8.4 matrix.

Current numbers: **293 tests / 391 assertions / 96.46 % line coverage**.

Contributing
------------

[](#contributing)

The contribution workflow, code style, and pull-request template are shared across the InitORM organization. See [InitORM/.github → CONTRIBUTING](https://github.com/InitORM/.github/blob/main/CONTRIBUTING.md)and the [PR template](https://github.com/InitORM/.github/blob/main/PULL_REQUEST_TEMPLATE.md). A short summary:

1. Branch from `master`.
2. Stick to **PSR-12**; run `composer qa` before opening a PR.
3. Add tests for new behavior — the test suite is the contract.
4. Reference issues with `Fixes #123` / `Refs #123`.

Security issues should follow the disclosure process in [InitORM/.github → SECURITY](https://github.com/InitORM/.github/blob/main/SECURITY.md).

Versioning
----------

[](#versioning)

This package follows [Semantic Versioning](https://semver.org). The behavioral and structural changes between 1.x and 2.x are listed in [CHANGELOG.md](CHANGELOG.md).

License
-------

[](#license)

MIT — see [LICENSE](LICENSE).

Credits
-------

[](#credits)

Authored and maintained by [Muhammet ŞAFAK](https://www.muhammetsafak.com.tr)&lt;&gt;. Issues and contributions are welcome on [GitHub](https://github.com/InitORM/QueryBuilder).

###  Health Score

44

—

FairBetter than 90% of packages

Maintenance89

Actively maintained with recent releases

Popularity10

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity58

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 86.7% 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 ~180 days

Recently: every ~223 days

Total

6

Last Release

75d ago

Major Versions

1.x-dev → 2.0.02026-05-24

PHP version history (2 changes)1.0PHP &gt;=8.0

2.0.0PHP ^8.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/4b6b34f3ac8938d8ee52ba3bd260680855dc5715c7b2929d9380de30d15a67dd?d=identicon)[muhammetsafak](/maintainers/muhammetsafak)

---

Top Contributors

[![muhammetsafak](https://avatars.githubusercontent.com/u/104234499?v=4)](https://github.com/muhammetsafak "muhammetsafak (13 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (2 commits)")

---

Tags

databasemariadbmysqlpdophpphp-libraryphp8postgresqlquery-buildersqlsql-buildersqliteormmysqlsqlitesqlpdopgsqlquery builderinitorm

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/initorm-query-builder/health.svg)

```
[![Health](https://phpackages.com/badges/initorm-query-builder/health.svg)](https://phpackages.com/packages/initorm-query-builder)
```

###  Alternatives

[doctrine/dbal

Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.

9.7k614.3M7.3k](/packages/doctrine-dbal)[cycle/orm

PHP DataMapper ORM and Data Modelling Engine

1.3k922.8k86](/packages/cycle-orm)[aura/sqlquery

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

4573.2M40](/packages/aura-sqlquery)[cycle/database

DBAL, schema introspection, migration and pagination

71811.3k65](/packages/cycle-database)[atlas/query

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

43260.2k7](/packages/atlas-query)[aura/sqlschema

Provides facilities to read table names and table columns from a database using PDO.

41245.4k4](/packages/aura-sqlschema)

PHPackages © 2026

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