Introduction
Condition Builder
Table of Contents
The Condition Builder provides a fluent API for building WHERE conditions incrementally. It's particularly useful when conditions need to be constructed dynamically based on runtime logic, such as building filter queries from user input.
Basic Usage
<?php
use function Flow\PostgreSql\DSL\{
conditions, select, table, col, eq, gt, param, literal
};
// Create a condition builder and add conditions fluently
$conditions = conditions()
->and(eq(col('status'), literal('active')))
->and(gt(col('age'), literal(18)));
// Use in a query
$query = select()->from(table('users'))->where($conditions);
echo $query->toSQL();
// SELECT * FROM users WHERE status = 'active' AND age > 18
Building Conditions Incrementally
The real power of ConditionBuilder is building conditions based on runtime logic:
<?php
use function Flow\PostgreSql\DSL\{
conditions, select, table, col, eq, gte, like, param
};
function buildUserQuery(array $filters): SelectFinalStep
{
$conditions = conditions();
if (array_key_exists('status', $filters)) {
$conditions = $conditions->and(eq(col('status'), param($filters['status'])));
}
if (array_key_exists('min_age', $filters)) {
$conditions = $conditions->and(gte(col('age'), param($filters['min_age'])));
}
if (array_key_exists('email_domain', $filters)) {
$conditions = $conditions->and(like(col('email'), param('%@' . $filters['email_domain'])));
}
$query = select()->from(table('users'));
// Only add WHERE clause if we have conditions
if (!$conditions->isEmpty()) {
$query = $query->where($conditions);
}
return $query;
}
// Usage
$query = buildUserQuery(['status' => 'active', 'min_age' => 21]);
echo $query->toSQL();
// SELECT * FROM users WHERE status = $1 AND age >= $2
Nested Conditions
Build complex nested conditions with OR groups inside AND:
<?php
use function Flow\PostgreSql\DSL\{
conditions, select, table, col, eq, gt, literal
};
// WHERE status = 'active' AND (role = 'admin' OR role = 'moderator') AND age > 18
$conditions = conditions()
->and(eq(col('status'), literal('active')))
->and(
conditions()
->or(eq(col('role'), literal('admin')))
->or(eq(col('role'), literal('moderator')))
)
->and(gt(col('age'), literal(18)));
$query = select()->from(table('users'))->where($conditions);
echo $query->toSQL();
// SELECT * FROM users WHERE status = 'active' AND (role = 'admin' OR role = 'moderator') AND age > 18
Immutability
ConditionBuilder is immutable - each and() or or() call returns a new builder instance:
<?php
use function Flow\PostgreSql\DSL\{conditions, eq, gt, col, literal};
$base = conditions()->and(eq(col('active'), literal(true)));
// Each branch creates a new builder
$withRole = $base->and(eq(col('role'), literal('admin')));
$withAge = $base->and(gt(col('age'), literal(18)));
// $base is unchanged
Empty Builder Behavior
isEmpty()returnstruewhen no conditions have been addedgetCondition()returnsnullfor empty builders- Passing an empty builder to
where()throwsInvalidBuilderStateException - Empty nested builders are ignored (no-op) when combined with
and()oror()
<?php
use function Flow\PostgreSql\DSL\{conditions, eq, col, literal};
$conditions = conditions();
// Safe pattern: check before using
if (!$conditions->isEmpty()) {
$query = $query->where($conditions);
}
// Empty nested builders are safely ignored
$conditions = conditions()
->and(eq(col('status'), literal('active')))
->and(conditions()); // Empty conditions is ignored
// Result: only "status = 'active'" condition
Method Reference
| Method | Description |
|---|---|
conditions() |
DSL function - creates a new empty ConditionBuilder |
and(Condition|ConditionBuilder $condition) |
Add a condition with AND logic |
or(Condition|ConditionBuilder $condition) |
Add a condition with OR logic |
getCondition() |
Returns the built Condition or null if empty |
isEmpty() |
Returns true if no conditions have been added |
Comparison with cond_and/cond_or
For static conditions known at build time, cond_and() and cond_or() are simpler:
// Static conditions - use cond_and/cond_or
$query = select()
->from(table('users'))
->where(cond_and(
eq(col('active'), literal(true)),
gt(col('age'), literal(18))
));
// Dynamic conditions - use ConditionBuilder
$conditions = conditions();
foreach ($filters as $filter) {
$conditions = $conditions->and($filter->toCondition());
}