PHPackages                             abterphp/qb - 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. abterphp/qb

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

abterphp/qb
===========

PHP SQL query builder

019PHP

Since Jul 6Pushed 4y ago1 watchersCompare

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

READMEChangelogDependenciesVersions (1)Used By (0)

qb
==

[](#qb)

[![Github Actions Build](https://github.com/abterphp/qb/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/abterphp/qb/actions)[![Scrutinizer Quality](https://camo.githubusercontent.com/4367cbfab91b020f896c4cf8ad5a0289c9079939a897b88c4f137ddf9b690ba1/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f61627465727068702f71622f6261646765732f7175616c6974792d73636f72652e706e673f623d6d61696e)](https://scrutinizer-ci.com/g/abterphp/qb/?branch=main)[![Scrutinizer Build](https://camo.githubusercontent.com/ee377a177d6f136ebabdb09064a2821b72cd14a67875ff57a70f3227b0b4b577/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f61627465727068702f71622f6261646765732f6275696c642e706e673f623d6d61696e)](https://scrutinizer-ci.com/g/abterphp/qb/build-status/main)[![Scrutinizer Coverage](https://camo.githubusercontent.com/c633943d97b0866eebee3b1cf906bc0fdd71e84af156098a8817aabbee4ab8a8/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f61627465727068702f71622f6261646765732f636f7665726167652e706e673f623d6d61696e)](https://scrutinizer-ci.com/g/abterphp/qb/?branch=main)[![Code Climate Quality](https://camo.githubusercontent.com/9e8cbb68cb785fcc7d133180351a65e267db862bd5c843a298c48828be34a370/68747470733a2f2f6170692e636f6465636c696d6174652e636f6d2f76312f6261646765732f64653534333863363466363462326262613134392f6d61696e7461696e6162696c697479)](https://codeclimate.com/github/abterphp/qb/maintainability)[![Code Climate Coverage](https://camo.githubusercontent.com/6b2dad23e32dd809de2bbbd51e42cfc538777391a0f485cbb6cec8d7d27f0205/68747470733a2f2f6170692e636f6465636c696d6174652e636f6d2f76312f6261646765732f64653534333863363466363462326262613134392f746573745f636f766572616765)](https://codeclimate.com/github/abterphp/qb/test_coverage)

QB is a generic query build which currently supports the base commands of MySQL and PostgreSQL.

- QB aims to support over 95% of use cases, not 100%
- There's still a bit to go for PostgreSQL support, MySQL should already be there.
- Pull requests for supporting other databases and commands are welcome.
- Written because most other projects do not support joining tables over other joined tables. (Many-to-many support)

### Examples

[](#examples)

#### MySQL SELECT with union

[](#mysql-select-with-union)

```
use QB\Generic\Clause\Column;
use QB\Generic\Clause\QueryAsTable;
use QB\Generic\Clause\Table;
use QB\Generic\Expr\Expr;
use QB\MySQL\Clause\CombiningQuery;
use QB\MySQL\Clause\Lock;
use QB\MySQL\Statement\Select;

$columnQuery = (new Select())
    ->from('quix')
    ->columns('b')
    ->where(new Expr('id = ?', [7]));

$columnExpr = new Expr('NOW()');

$joinQuery = (new Select())->from(new Table('quix', 'q2'))->where('q2.foo_id = foo.id');

$unionQuery = (new Select('b', 'f'))->from('baz');

$sql = (string)(new Select('COUNT(DISTINCT baz) AS baz_count', new Column($columnQuery, 'quix_b')))
    ->from('foo', 'bar')
    ->modifier('DISTINCT')
    ->columns(new Column($columnExpr, 'now'))
    ->columns(new Column('bar.id', 'bar_id'))
    ->innerJoin(new Table('quix', 'q'), 'foo.id = q.foo_id')
    ->innerJoin(new QueryAsTable($joinQuery, 'q2'))
    ->where('foo.bar = "foo-bar"', new Expr('bar.foo = ?', ['bar-foo']))
    ->where(new Expr('bar.foo IN (?)', [['bar', 'foo']]))
    ->groupBy('q.foo_id', new Expr('q.bar.id'))
    ->groupWithRollup()
    ->having('baz_count > 0')
    ->orderBy('baz_count', 'ASC')
    ->limit(10)
    ->offset(20)
    ->lock(new Lock(Lock::FOR_UPDATE, ['foo'], Lock::MODIFIER_NOWAIT))
    ->union($unionQuery, CombiningQuery::MODIFIER_DISTINCT);

// SELECT DISTINCT COUNT(DISTINCT baz) AS baz_count, (SELECT b FROM quix WHERE id = ?) AS quix_b, NOW() AS now, bar.id AS bar_id
// FROM foo, bar
// INNER JOIN quix AS q ON foo.id = q.foo_id
// INNER JOIN (SELECT * FROM quix AS q2 WHERE foo.id = q2.foo_id) AS q2
// WHERE foo.bar = "foo-bar" AND bar.foo = ? AND bar.foo IN (?, ?)
// GROUP BY q.foo_id, q.bar.id WITH ROLLUP
// HAVING baz_count > 0
// ORDER BY baz_count ASC
// LIMIT 20, 10
// FOR UPDATE OF foo NOWAIT
// UNION DISTINCT
// SELECT b, f
// FROM baz
```

#### PostgreSQL INSERT with UPDATE ON CONFLICT AND RETURNING

[](#postgresql-insert-with-update-on-conflict-and-returning)

```
use QB\Generic\Clause\Table;
use QB\PostgreSQL\Statement\Insert;

$sql = (string)(new Insert())
    ->into(new Table('offices'))
    ->columns('officeCode', 'city', 'phone', 'addressLine1', 'country', 'postalCode', 'territory')
    ->values('abc', 'Berlin', '+49 101 123 4567', '', 'Germany', '10111', 'NA')
    ->values('bcd', 'Budapest', '+36 70 101 1234', '', 'Hungary', '1011', 'NA')
    ->onConflict('officeCode', 'city')
    ->doUpdate('officeCode = EXCLUDED.officeCode', 'city = EXCLUDED.city')
    ->returning('*');

// INSERT INTO offices (officeCode, city, phone, addressLine1, country, postalCode, territory)
// VALUES (?, ?, ?, ?, ?, ?, ?),
// (?, ?, ?, ?, ?, ?, ?)
// ON CONFLICT (officeCode, city) DO UPDATE
// SET officeCode = EXCLUDED.officeCode, city = EXCLUDED.city
// RETURNING *
```

#### Custom command

[](#custom-command)

```
use QB\Generic\Statement\Select;
use QB\Generic\Statement\Command;

$select = (new Select())
    ->from('quix')
    ->columns('b');

$sql = (string)(new Command('EXPLAIN %s', $select));

// EXPLAIN SELECT b FROM quix
```

###  Health Score

17

—

LowBetter than 6% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity6

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity29

Early-stage or recently created project

 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.

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/47573042?v=4)[abtercms](/maintainers/abtercms)[@abtercms](https://github.com/abtercms)

---

Top Contributors

[![peteraba](https://avatars.githubusercontent.com/u/1675360?v=4)](https://github.com/peteraba "peteraba (45 commits)")

### Embed Badge

![Health badge](/badges/abterphp-qb/health.svg)

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

###  Alternatives

[jdorn/sql-formatter

a PHP SQL highlighting library

3.9k117.2M117](/packages/jdorn-sql-formatter)[propel/propel1

Propel is an open-source Object-Relational Mapping (ORM) for PHP5.

8351.6M87](/packages/propel-propel1)[jfelder/oracledb

Oracle DB driver for Laravel

11518.4k](/packages/jfelder-oracledb)

PHPackages © 2026

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