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

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

zlikavac32/query-builder
========================

The SQL query builder library that never builds an SQL query from scratch, but rather modifies an existing query.

024PHPCI failing

Since Apr 18Pushed 6y ago1 watchersCompare

[ Source](https://github.com/zlikavac32/query-builder)[ Packagist](https://packagist.org/packages/zlikavac32/query-builder)[ RSS](/packages/zlikavac32-query-builder/feed)WikiDiscussions master Synced 6d ago

READMEChangelogDependenciesVersions (1)Used By (0)

Query Builder
=============

[](#query-builder)

[![Build Status](https://camo.githubusercontent.com/c47832735175614db798c69ab3dd54e9f63ee68be7aeff0b3046e3f71a9261f0/68747470733a2f2f7472617669732d63692e6f72672f7a6c696b6176616333322f71756572792d6275696c6465722e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/zlikavac32/query-builder) [![Latest Stable Version](https://camo.githubusercontent.com/a7d0beac61f7c3741abe9be00527cfb2fbc2b28fe15ce16278b88a197878b087/68747470733a2f2f706f7365722e707567782e6f72672f7a6c696b6176616333322f71756572792d6275696c6465722f762f737461626c65)](https://packagist.org/packages/zlikavac32/query-builder) [![License](https://camo.githubusercontent.com/8db5e21cc22e04c86e5a02e711385dea6c49256c46ffbb42b98f16ac31020824/68747470733a2f2f706f7365722e707567782e6f72672f7a6c696b6176616333322f71756572792d6275696c6465722f6c6963656e7365)](https://packagist.org/packages/zlikavac32/query-builder)

The SQL query builder library that does not build an SQL query from scratch, but rather modifies an existing query.

Table of contents
-----------------

[](#table-of-contents)

1. [Introduction](#introduction)
2. [How it works](#how-it-works)
3. [Installation](#installation)
4. [Configuration](#configuration)
    1. [Preloading](#preloading)
5. [Usage](#usage)
    1. [Subquery inlining](#subquery-inlining)
6. [Limitations](#limitations)

Introduction
------------

[](#introduction)

How to achieve harmony between the PHP and the database has been a subject to many blog posts. While some propose and use various ORM-s like Doctrine and Eloquent, other stick to raw SQL queries. ORM-s come with some sort of a query builder that is something very useful. For example, when providing filtering to an admin page, it's useful to programmatically modify the query to reflect requested filters.

If we think about a query itself, there are really rare occasions (I myself did not encounter one such) where we need to build a query from scratch. We usually have a base query that does something and then we extend it. In the filtering example above, we could have `SELECT t.id, t.name FROM tickets t WHERE t.date >= '2020-01-01` as a base query for this years tickets and then a filter for `state` that modifies initial query into `SELECT t.id, t.name FROM tickets t WHERE t.date > '2020-01-01' AND t.state = 'SOLD'`.

That is the main premise behind this query builder. To reuse existing queries instead of manually constructing a full query through the query builder.

How it works?
-------------

[](#how-it-works)

Every `SELECT` statement is decomposed into sections like `columns` or `where` and then that statement can be modified through the exposed query builder API. To make that possible, the query builder parses statements and tracks all of the parameter placeholders and parameter values themselves and when a certain section is modified, parameters are merged/removed as well.

That means that parameters must be known at the time when that section is being added to the query builder, whether it's the initial query or just some new section. That being said, this query builder is not intended for reusable prepared statements (**yet!**).

The parser used is a [small SQL parser](https://github.com/zlikavac32/sql-query-parser) written in C and exposed through the FFI (more parser implementations may come in the future).

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

[](#installation)

The recommended installation is through Composer.

```
composer require zlikavac32/query-builder
```

Configuration
-------------

[](#configuration)

To use the query builder, create a query builder environment.

```
use Zlikavac32\QueryBuilder\FFISqlParser;
use Zlikavac32\QueryBuilder\NonPreloadedFFIGateway;
use Zlikavac32\QueryBuilder\ParserBackedQueryEnvironment;

$parser = NonPreloadedFFIGateway::createDefault();
$parser = new FFISqlParser($parser);
$queryBuilder = new ParserBackedQueryEnvironment($parser);
```

### Preloading

[](#preloading)

Instead of importing the FFI definition when needed, the FFI definition can be preloaded. There is no pretty or automatic way to do it. In your preload script you should add

```
FFI::load('{{path}}');
```

where `{{path}}` represents a path to the `tsqlp.h` header file in this repository, for example `__DIR__ . '/vendor/zlikavac32/query-builder/tsqlp.h`. Other (perhaps necessary) option is to use `ffi.preload` with the path to the `tsqlp.h`. For more info consult the [FFI configuration](https://www.php.net/manual/en/ffi.configuration.php).

Other change is that you can no longer use the `\Zlikavac32\QueryBuilder\NonPreloadedFFIGateway` class and you should use the `\Zlikavac32\QueryBuilder\PreloadedFFIGateway` class.

Usage
-----

[](#usage)

Use the constructed environment to create a query builder from an `SQL` string or a `\Zlikavac32\QueryBuilder\Query` instance.

```
$qb = $queryBuilder->queryBuilderFromString(
    'SELECT * FROM user WHERE active = ?',
    1
);

$qb->andWhere('registered_at > ?', '2020-01-01');

$query = $qb->build();

var_dump($query->sql(), $query->parameters());
// SELECT * FROM user WHERE (active = ?) AND (registered_at > ?)
// [1, '2020-01-01']
```

Check `\Zlikavac32\QueryBuilder\QueryBuilder` for more info regarding available query builder methods.

### Subquery inlining

[](#subquery-inlining)

Since this library parses queries, it can inject subqueries into the parameter placeholders.

```
use Zlikavac32\QueryBuilder\Query;

$userOfTheLatestTransactionQuery = Query::create(
    'SELECT user_id FROM transaction ORDER BY created_at DESC LIMIT 1'
);
$qb = $queryBuilder->queryBuilderFromString(
    'SELECT * FROM user WHERE id = ?',
    $userOfTheLatestTransactionQuery
);

$query = $qb->build();

var_dump($query->sql(), $query->parameters());
// SELECT * FROM user WHERE id = (SELECT user_id FROM transaction ORDER BY date DESC LIMIT 1)
// []
```

Limitations
-----------

[](#limitations)

Used parser could (and probably will) parse certain SQL queries as valid only for them to be rejected from the database. This is by design to keep the parsing simple since that parser is not intended to be used as a linter or whatever. It doesn't even produce an AST and the resulting query will immediately be executed so the logic error will be known. The query builder itself will not produce an invalid query from a valid query. This is not really a limitation, but it's useful to mention.

###  Health Score

18

—

LowBetter than 8% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity6

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity34

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://www.gravatar.com/avatar/b47ffc503d7c4536136bc08ed1185682bec5789108bd7a2cf7edfee98994dfef?d=identicon)[zlikavac32](/maintainers/zlikavac32)

---

Top Contributors

[![zlikavac32](https://avatars.githubusercontent.com/u/1078270?v=4)](https://github.com/zlikavac32 "zlikavac32 (20 commits)")

---

Tags

query-buildersql

### Embed Badge

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

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

###  Alternatives

[doctrine/orm

Object-Relational-Mapper for PHP

10.2k285.3M6.2k](/packages/doctrine-orm)[jdorn/sql-formatter

a PHP SQL highlighting library

3.9k115.1M102](/packages/jdorn-sql-formatter)[illuminate/database

The Illuminate Database package.

2.8k52.4M9.4k](/packages/illuminate-database)[mongodb/mongodb

MongoDB driver library

1.6k64.0M546](/packages/mongodb-mongodb)[ramsey/uuid-doctrine

Use ramsey/uuid as a Doctrine field type.

90340.3M211](/packages/ramsey-uuid-doctrine)[reliese/laravel

Reliese Components for Laravel Framework code generation.

1.7k3.4M16](/packages/reliese-laravel)

PHPackages © 2026

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