where() or orWhere()
The where() method is the most versatile condition builder in decMuc/PDOdb.
It supports all comparison operators, arrays, subqueries, SQL functions, and even custom injection-safe expressions.
where() inputs are internally checked for suspicious patterns such as
1; SLEEP(1), logic breaks, or unsafe casting. This heuristic system prevents many
types of SQL injection — even if untyped input is passed.
⚠️ For maximum safety, you should use type-specific filters like
whereInt() or
whereBool() where possible.
Advanced details: Heuristic WHERE check
This protection layer (internally called PDOdb_HEURISTIC_WHERE_CHECK) is enabled by default.
You can disable it globally or per instance if required.
Basic usage
The where() method adds a simple AND condition to the query.
It accepts one to three parameters, depending on the type of comparison:
where(column, value)– compares with=by defaultwhere(column, operator, value)– for custom operators like!=,>,LIKEetc.
$db->where('id', 5);
$db->where('status', 'active');
$db->where('price', '>', 10);
$db->where('title', 'LIKE', '%special%');
$db->get('products');
All where() conditions are automatically combined using AND.
Adding OR conditions
To add a logical OR between conditions, use the orWhere() method.
It accepts the same parameters as where() and must follow an existing condition.
$db->where('status', 'active');
$db->orWhere('status', 'pending');
$db->where('type', 'user');
$db->get('accounts');
This creates a query like:
SELECT * FROM accounts WHERE status = 'active' OR status = 'pending' AND type = 'user'
Mixing where() and orWhere()
You can chain where() and orWhere() freely to build complex conditions
during query composition. This gives you full flexibility for dynamic logic.
$db->where('type', 'user');
$db->orWhere('type', 'admin');
$db->where('active', 1);
$db->orWhere('email_verified', 1);
$db->get('users');
This builds a query like:
WHERE type = 'user' OR type = 'admin' AND active = 1 OR email_verified = 1
Note: Parentheses are not applied automatically.
What values are expected in where() conditions?
The where() and orWhere() methods support a wide range of input types.
However, not all combinations are valid. Here's what is supported:
- Scalar values (
int,string,float) null(converted toIS NULL/IS NOT NULL)- Arrays (for
IN/NOT IN) - Subqueries (objects with a
getSubQuery()method) - Special functions like
$db->now()
The $operator must be a valid SQL operator (e.g. =, >, LIKE, IN, IS NOT).
Anything else will be rejected automatically for safety reasons.
❌ Invalid Examples:
where('id', '1 OR 1=1') – flagged as suspicious
→ deferred and only blocked if id is a numeric or strict field
where('col', '(SELECT ... )') – raw subqueries as strings → not allowed
where('SUM(price)', 100) – aggregate functions → blocked
This validation is handled automatically by secureWhere() and can be extended via
whereInt(), whereDate(), and similar safe variants.
Chaining multiple where() and orWhere() calls
You can call where() and orWhere() repeatedly in any order.
All conditions are accumulated until the query is executed.
$db
->where('role', 'customer')
->where('country', 'DE')
->orWhere('newsletter_optin', 1);
$users = $db->get('users');
This generates:
WHERE role = 'customer' AND country = 'DE' OR newsletter_optin = 1
Checking for NULL and NOT NULL
You can check for NULL or NOT NULL values using the standard where() method by passing null as the value.
where('column', null)→ generatesIS NULLwhere('column', null, 'IS NOT')→ generatesIS NOT NULL
// Find all users where deleted_at IS NULL
$db->where('deleted_at', null);
// Find all orders where shipped_at IS NOT NULL
$db->where('shipped_at', null, 'IS NOT');
$db->get('orders');
All where() conditions are also available as orWhere() by simply changing the method name.
For improved type safety and readability, you can also use:
whereIS('column')– forIS NULLwhereIsNot('column')– forIS NOT NULL- ...and their
orWhereIS()/orWhereIsNot()counterparts
Using BETWEEN and NOT BETWEEN conditions
To filter a value range (e.g. prices or dates), pass an array with exactly two values and set the operator to
BETWEEN or NOT BETWEEN.
where('price', [10, 20], 'BETWEEN')→price BETWEEN 10 AND 20where('created_at', ['2020-01-01', '2020-12-31'], 'NOT BETWEEN')→ excludes that range
// Match range of prices
$db->where('price', [10, 20], 'BETWEEN');
// Exclude a date range
$db->where('created_at', ['2020-01-01', '2020-12-31'], 'NOT BETWEEN');
$db->get('products');
Use whereBetween() or
whereNotBetween() for type-safe variants.
These explicitly validate range values.
orWhere*() versions are also available.
Using LIKE and NOT LIKE
To match patterns in a column, use the SQL operators LIKE or NOT LIKE together with
percent signs (%) as wildcards.
The pattern is passed as a string, and you specify the operator explicitly.
where('name', 'John%', 'LIKE')→ starts with "John"where('email', '%@gmail.%', 'NOT LIKE')→ exclude Gmail addressesorWhere('notes', '%urgent%', 'LIKE')→ contains the word "urgent"
// Starts with 'admin'
$db->where('username', 'admin%', 'LIKE');
// Excludes Gmail addresses
$db->where('email', '%@gmail.%', 'NOT LIKE');
// Contains 'SQL injection'
$db->orWhere('notes', '%SQL injection%', 'LIKE');
$db->get('users');
LIKE and NOT LIKE are both fully supported.
Just pass the pattern and use the operator explicitly.
LIKE and NOT LIKE are both fully supported.
Just pass the pattern and use the operator explicitly.
EXISTS and NOT EXISTS
EXISTS and NOT EXISTS are fully supported and allow you to check whether a given subquery
returns any rows. To use these conditions, you must pass a subquery object created via
subQuery().
$sub = $db->subQuery('s');
$sub->where('user_id', $db->func('u.id'));
$sub->get('orders', 'user_id');
$db->where('EXISTS', $sub);
// or
$db->where('NOT EXISTS', $sub);
These advanced WHERE conditions rely on subquery support and cannot be used with plain SQL strings. For details and more examples, see Subqueries and Nested Conditions.