2017 © Pedro Peláez
 

library where

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

image

bentools/where

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

  • Thursday, April 5, 2018
  • by bpolaszek
  • Repository
  • 1 Watchers
  • 7 Stars
  • 163 Installations
  • PHP
  • 1 Dependents
  • 0 Suggesters
  • 0 Forks
  • 0 Open issues
  • 5 Versions
  • 44 % Grown

The README.md

Latest Stable Version License Build Status Coverage Status Quality Score Total Downloads, (*1)

Where

The simplest fluent SQL query builder ever., (*2)

Built in PHP7.1 with immutability in mind., (*3)

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?

In most cases simple SQL queries are fine., (*4)

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)., (*5)

Conditions builder

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

  • 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)., (*7)

You don't need to instanciate them. Just rely on the powerful functions the library offers:, (*8)

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:, (*9)

country IN (?, ?) AND NOT (continent = ? OR population < ?)

```php Array ( [0] => FRA [1] => UK [2] => Europe [3] => 100000 ), (*10)

```mysql
country IN ('FRA', 'UK') AND NOT (continent = 'Europe' OR population < 100000)

Every function where(), group(), not() accepts either an already instanciated Expression object, or a string and some optionnal parameters., (*11)

$where = where('date > NOW()'); // valid
$where = where($where); // valid
$where = where(group($where)); // valid
$where = where(not($where)); // valid
$where = where('date = ?', date('Y-m-d')); // valid
$where = where('date BETWEEN ? AND ?', date('Y-m-d'), date('Y-m-d')); // valid
$where = where('date BETWEEN ? AND ?', [date('Y-m-d'), date('Y-m-d')]); // valid
$where = where('date BETWEEN :start AND :end', ['start' => 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., (*12)

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:, (*13)

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., (*14)

RulerZ

Where is mostly compatible with the awesome RulerZ DSL., (*15)

Be sure to group your statements to avoid downside effects., (*16)

Example:, (*17)

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

composer require bentools/where, (*18)

Tests

./vendor/bin/phpunit, (*19)

See also

bentools/simple-dbal - A PHP 7.1+ wrapper for PDO & Mysqli. Can bind DateTime parameters., (*20)

bentools/pager - A PHP 7.1+ pager., (*21)

bentools/flatten-iterator - Flattens multiple array or Traversable into one iterator., (*22)

bentools/etl - A PHP7.1 ETL pattern implementation., (*23)

latitude/latitude - Another SQL Query builder Where was inspired of., (*24)

The Versions

05/04 2018

dev-master

9999999-dev

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

  Sources   Download

MIT

The Requires

  • php ^7.1

 

The Development Requires

database sql update query delete select mysql field query builder case builder insert conditions where then when

04/04 2018

1.1.1

1.1.1.0

PHP7.1 Fluent, immutable SQL query builder.

  Sources   Download

MIT

The Requires

 

The Development Requires

database sql select mysql query builder conditions where

17/11 2017

1.1

1.1.0.0

PHP7.1 Fluent, immutable SQL query builder.

  Sources   Download

MIT

The Requires

 

The Development Requires

database sql select mysql query builder conditions where

04/10 2017

1.0.1

1.0.1.0

PHP7.1 Fluent, immutable SQL query builder.

  Sources   Download

MIT

The Requires

 

The Development Requires

database sql select mysql query builder conditions where

26/09 2017

1.0

1.0.0.0

PHP7.1 Fluent, immutable SQL query builder.

  Sources   Download

MIT

The Requires

 

The Development Requires

database sql select mysql query builder conditions where