PHPackages                             bentools/where - 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. bentools/where

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

bentools/where
==============

PHP7.1 Fluent, immutable SQL query builder. Connectionless, framework-agnostic, no dependency.

1.4(6y ago)125.2k12MITPHPPHP &gt;=7.1

Since Sep 26Pushed 6y ago1 watchersCompare

[ Source](https://github.com/bpolaszek/where)[ Packagist](https://packagist.org/packages/bentools/where)[ RSS](/packages/bentools-where/feed)WikiDiscussions master Synced 3d ago

READMEChangelog (3)Dependencies (4)Versions (9)Used By (2)

[![Latest Stable Version](https://camo.githubusercontent.com/6065d9c8693687514aeef4cffadba15154a62b641e073bc6f72bd7c7b77fa191/68747470733a2f2f706f7365722e707567782e6f72672f62656e746f6f6c732f77686572652f762f737461626c65)](https://packagist.org/packages/bentools/where)[![License](https://camo.githubusercontent.com/4b244949f08b18bcca8c0e721f80a410d48a2d687e3c035454b38c5aea8ee09b/68747470733a2f2f706f7365722e707567782e6f72672f62656e746f6f6c732f77686572652f6c6963656e7365)](https://packagist.org/packages/bentools/where)[![Build Status](https://camo.githubusercontent.com/434d31f12e9d88661e5a8db4004326f0615a63e31450de415d65e46a0d2101da/68747470733a2f2f696d672e736869656c64732e696f2f7472617669732f62706f6c61737a656b2f77686572652f6d61737465722e7376673f7374796c653d666c61742d737175617265)](https://travis-ci.org/bpolaszek/where)[![Coverage Status](https://camo.githubusercontent.com/938096d00e26eca60c47ffadf75965523e0547b60760a84089a75ed9f7487d92/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f6769746875622f62706f6c61737a656b2f77686572652f62616467652e7376673f6272616e63683d6d6173746572)](https://coveralls.io/github/bpolaszek/where?branch=master)[![Quality Score](https://camo.githubusercontent.com/358df2724343f76dd5c1b262566e4d6c975ac00e226359dd2abf878fc3f58e03/68747470733a2f2f696d672e736869656c64732e696f2f7363727574696e697a65722f672f62706f6c61737a656b2f77686572652e7376673f7374796c653d666c61742d737175617265)](https://scrutinizer-ci.com/g/bpolaszek/where)[![Total Downloads](https://camo.githubusercontent.com/8d5bf555cf64f593249f2c2fad4b7b540176b92688ed8419a93818b5c836249f/68747470733a2f2f706f7365722e707567782e6f72672f62656e746f6f6c732f77686572652f646f776e6c6f616473)](https://packagist.org/packages/bentools/where)

Where
=====

[](#where)

The simplest fluent SQL query builder ever.

Built in PHP7.1 with immutability in mind.

Features
--------

[](#features)

- Framework agnostic, connection agnostic (you just render a string and an array of values)
- Natural language: where, and, or, ...
- Support named and numeric placeholders
- Build complex, nested WHERE conditions
- Helpers for building `SELECT`, `INSERT`, `UPDATE`, `DELETE`, `REPLACE` queries
- Helpers for SQL functions like `IN`, `BETWEEN`, `IS NULL`, `CASE ... WHEN`

Why?
----

[](#why)

In most cases simple SQL queries are fine.

But if your application logic is designed in a way that several classes / methods can modify an SQL query (like the Visitor pattern), then you'll probably need query builder (you can define LIMIT / OFFSET before WHERE for instance, and the query will be rendered in the correct order).

Conditions builder
------------------

[](#conditions-builder)

**Where** allows you to build your conditions with **Expressions**. **Expressions** are objects that can be:

- Simple expressions: `date_added = CURRENT_DATE`
- Composite expressions: `date_added = CURRENT_DATE OR date_added = SUBDATE(CURRENT_DATE, INTERVAL 1 DAY)`
- Group expressions: `(country = 'UK' OR country = 'BE')`
- Negated expressions: `NOT date_added = CURRENT_DATE`

An **Expression** object can also contain an array of parameters to bind (to avoid SQL injections).

You don't need to instanciate them. Just rely on the powerful functions the library offers:

```
require_once __DIR__ . '/vendor/autoload.php';

use function BenTools\Where\group;
use function BenTools\Where\not;
use function BenTools\Where\where;

$where = where('country IN (?, ?)', ['FRA', 'UK'])
    ->and(
        not(
            group(
                where('continent = ?', 'Europe')
                    ->or('population < ?', 100000)
            )
        )
    );

print((string) $where);
print_r($where->getValues());
print_r($where->preview());  // For debugging purposes
```

Outputs:

```
country IN (?, ?) AND NOT (continent = ? OR population  FRA
    [1] => UK
    [2] => Europe
    [3] => 100000
)
```

```
country IN ('FRA', 'UK') AND NOT (continent = 'Europe' OR population  date('Y-m-d'), 'end' => date('Y-m-d')]); // valid
$where = where('date BETWEEN :start AND :end', ['start' => date('Y-m-d')], ['end' => date('Y-m-d')]); // not valid
$where = where($where, date('Y-m-d'), date('Y-m-d')); // not valid (parameters already bound)
```

Thanks to the fluent interface, let your IDE guide you for the rest. Don't forget **Where** is always immutable: reassign `$where` everytime you do some changes.

Select Query Builder
--------------------

[](#select-query-builder)

Now you've learnt how to build conditions, you'll see how building a whole select query is a piece of cake:

```
require_once __DIR__ . '/vendor/autoload.php';

use function BenTools\Where\group;
use function BenTools\Where\not;
use function BenTools\Where\select;
use function BenTools\Where\where;

$select = select('b.id', 'b.name  AS book_name', 'a.name AS author_name')
    ->from('books as b')
    ->innerJoin('authors as a', 'a.id = b.author_id')
    ->limit(10)
    ->orderBy('YEAR(b.published_at) DESC', 'MONTH(b.published_at) DESC', 'b.name')
    ->where(
        group(
            where('b.series = ?', 'Harry Potter')->or('b.series IN (?, ?)', ['A Song of Ice and Fire', 'Game of Thrones'])
        )
            ->and('b.published_at >= ?', new \DateTime('2010-01-01'))
        ->and(
            not('b.reviewed_at BETWEEN ? AND ?', new \DateTime('2016-01-01'), new \DateTime('2016-01-31 23:59:59'))
        )
    );
print_r((string) $select); // The SQL string
print_r($select->preview()); // For debugging purposes
```

```
SELECT b.id, b.name  AS book_name, a.name AS author_name
FROM books as b
INNER JOIN authors as a ON a.id = b.author_id
WHERE (b.series = ? OR b.series IN (?, ?))
AND b.published_at >= ?
AND NOT b.reviewed_at BETWEEN ? AND ?
ORDER BY YEAR(b.published_at) DESC, MONTH(b.published_at) DESC, b.name
LIMIT 10;
```

```
SELECT b.id, b.name  AS book_name, a.name AS author_name
FROM books as b
INNER JOIN authors as a ON a.id = b.author_id
WHERE (b.series = 'Harry Potter' OR b.series IN ('A Song of Ice and Fire', 'Game of Thrones'))
AND b.published_at >= '2010-01-01 00:00:00'
AND NOT b.reviewed_at BETWEEN '2016-01-01 00:00:00' AND '2016-01-31 23:59:59'
ORDER BY YEAR(b.published_at) DESC, MONTH(b.published_at) DESC, b.name
LIMIT 10;
```

Let your favorite IDE do the rest with autocompletion.

RulerZ
------

[](#rulerz)

**Where** is mostly compatible with the awesome [RulerZ](https://github.com/K-Phoen/rulerz) DSL.

Be sure to `group` your statements to avoid downside effects.

Example:

```
use function BenTools\Where\group;
use function BenTools\Where\not;

$fruits = [
    'banana',
    'apple',
];

$colors = [
    'yellow',
    'red',
];

$condition = group('fruit IN :fruits', ['fruits' => $fruits])->and(group('color IN :colors', ['colors' => $colors]));
$condition = not($condition);

var_dump($rulerz->satisfies(['fruit' => 'strawberry', 'color' => 'red'], (string) $condition, $condition->getValues())); // true
var_dump($rulerz->satisfies(['fruit' => 'apple', 'color' => 'yellow'], (string) $condition, $condition->getValues())); // false
```

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

[](#installation)

> composer require bentools/where

Tests
-----

[](#tests)

> ./vendor/bin/phpunit

See also
--------

[](#see-also)

[bentools/simple-dbal](https://github.com/bpolaszek/simple-dbal) - A PHP 7.1+ wrapper for PDO &amp; Mysqli. Can bind `DateTime` parameters.

[bentools/pager](https://github.com/bpolaszek/bentools-pager) - A PHP 7.1+ pager.

[bentools/flatten-iterator](https://github.com/bpolaszek/flatten-iterator) - Flattens multiple `array` or `Traversable` into one iterator.

[bentools/etl](https://github.com/bpolaszek/bentools-etl) - A PHP7.1 ETL pattern implementation.

[latitude/latitude](https://github.com/shadowhand/latitude) - Another SQL Query builder **Where** was inspired of.

###  Health Score

33

—

LowBetter than 75% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity25

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity63

Established project with proven stability

 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

Every ~110 days

Recently: every ~153 days

Total

7

Last Release

2489d ago

PHP version history (2 changes)1.0PHP ^7.1

1.4PHP &gt;=7.1

### Community

Maintainers

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

---

Top Contributors

[![bpolaszek](https://avatars.githubusercontent.com/u/5569077?v=4)](https://github.com/bpolaszek "bpolaszek (23 commits)")

---

Tags

databasemysqlsqlquerybuilderfieldquery builderselectupdatedeleteinsertcaseconditionswherethenwhen

###  Code Quality

TestsPHPUnit

Code StylePHP\_CodeSniffer

### Embed Badge

![Health badge](/badges/bentools-where/health.svg)

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

###  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)[atlas/query

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

41249.0k7](/packages/atlas-query)[nilportugues/sql-query-builder

An elegant lightweight and efficient SQL QueryInterface BuilderInterface supporting bindings and complicated query generation.

425239.4k6](/packages/nilportugues-sql-query-builder)[opis/database

A database abstraction layer over PDO, that provides a powerful and intuitive query builder, bundled with an easy to use schema builder

10184.2k3](/packages/opis-database)[codesvault/howdy-qb

Mysql Query Builder for WordPress

371.2k1](/packages/codesvault-howdy-qb)

PHPackages © 2026

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