DatabaseQuery

An abstract base class for building SQL queries with parameterized bind values

Provides a fluent interface for composing query clauses that can be safely passed between methods and objects without knowledge of what other methods have added. Subclasses include DatabaseQuerySelect for SELECT queries and DatabaseQuerySelectFulltext for fulltext search queries.

You do not typically instantiate DatabaseQuery directly—use one of its concrete subclasses instead.

$query = new DatabaseQuerySelect();
$query->select("id, name")->from("pages")->where("status>?", 0)->orderby("name")->limit(25);
Building queries (fluent interface)

All registered query methods (such as select, from, where, join, leftjoin, orderby, groupby, limit) are available as chainable methods via __call(). Each call appends to the existing clause, allowing multiple calls to build up complex queries incrementally.

$query = new DatabaseQuerySelect();
$query->select("id, name, status");
$query->from("pages");
$query->from("pages_sortfields"); // adds another table to FROM
$query->where("pages.parent_id=?", 10);
$query->where("pages.status>?", 0); // appends AND clause
$query->orderby("sortfield");
$query->limit(50);

Named parameters

Pass bind values as an associative array in the second argument. Keys must start with : (the colon is auto-prepended if omitted):

$query->where("name=:name AND status=:status", [':name' => 'about', ':status' => 1]);

Implied parameters (positional)

Use ? placeholders with a regular (numeric-keyed) array of values:

$query->where("name=? AND status=?", ['about', 1]);

When there is only one ? placeholder, the value does not need to be wrapped in an array:

$query->where("parent_id=?", 10);

Resetting a clause

Pass null to clear an existing clause 3.0.257:

$query->where(null); // clears all WHERE conditions

Combining queries

Use copyTo() to merge clauses from one query into another:

$queryA = new DatabaseQuerySelect();
$queryA->where("status>?", 0);
$queryA->orderby("name");

$queryB = new DatabaseQuerySelect();
$queryA->copyTo($queryB);  // copies all clauses to $queryB
$queryA->copyBindValuesTo($queryB); // copies bind values too
Bind values

bindValue($key, $value, $type = null)

Bind a named parameter to a value. The key is auto-prefixed with : if not already present.

$query->bindValue(':name', 'hello');
$query->bindValue('status', 1);  // colon auto-prepended

The optional $type argument accepts 'string', 'int', 'bool', 'null', or a PDO::PARAM_* constant.

bindValueGetKey($value, $type = null)

Bind a value and return a unique auto-generated key name in one step. Useful for building dynamic queries:

$key = $query->bindValueGetKey('hello'); // returns a unique key like ":s0X"
$query->where("name=$key");

bindValues($bindValues = null)

Get or set multiple bind values at once. When called with no arguments, returns the current bind values array. When given an array, merges those values into the existing bind values (does not replace).

// Get all bind values
$values = $query->bindValues();

// Set multiple bind values
$query->bindValues([':name' => 'about', ':status' => 1]);

getBindValues($options = array())

Get bind values with options. Supports the following options:

  • query (\PDOStatement|DatabaseQuery): Copy bind values to this query object.
  • count (bool): Return count instead of array 3.0.157.
  • inSQL (string): Only return bind values referenced in the given SQL string.
// Copy to a PDOStatement
$stmt = $database->prepare($query->getQuery());
$query->getBindValues(['query' => $stmt]);

// Count bind values
$count = $query->getBindValues(['count' => true]);

copyBindValuesTo($query, $options = [])

Copy bind values from this query to another DatabaseQuery or PDOStatement. Returns the number of values copied.

$numCopied = $queryA->copyBindValuesTo($queryB);

bindOption($optionName, $optionValue = null)

Get or set bind options. Options control how auto-generated bind keys are named:

  • prefix (string): Prefix for auto-generated keys (default: 'pw').
  • suffix (string): Suffix character (default: 'X').
  • global (bool): Make keys globally unique across all instances (default: false).
// Set global uniqueness for keys
$query->bindOption('global', true);

// Get all options
$allOptions = $query->bindOption(true);
Generating SQL

getQuery()

Returns the fully assembled SQL string. Also accessible via the $query->query or $query->sql property.

$sql = $query->getQuery();
// or
$sql = $query->query;

getSQL($method = '')

Alias for getQuery(). If $method is specified, returns the SQL for only that clause:

echo $query->getSQL('where'); // just the WHERE clause SQL
echo $query->getSQL('orderby'); // just the ORDER BY clause

getQueryMethod($method)

Returns the generated SQL for a specific query method/clause:

$whereSQL = $query->getQueryMethod('where');

getDebugQuery()

Returns the SQL query with bind parameters populated inline (for debugging only—not suitable for execution):

echo $query->getDebugQuery();
// SELECT id,name FROM `pages` WHERE status>0 ORDER BY name
Execution

prepare()

Prepares and returns a \PDOStatement with all bind values applied:

$stmt = $query->prepare();
$stmt->execute();
$results = $stmt->fetchAll(\PDO::FETCH_ASSOC);

execute($options = [])

Prepares and executes the query in one step. Handles connection loss with automatic retry.

Options:

  • throw (bool): Throw exceptions on error (default: true).
  • maxTries (int): Max retries on connection loss (default: 3).
  • returnQuery (bool): Return \PDOStatement if true, bool result of execute if false (default: true).
// Execute and get PDOStatement
$stmt = $query->execute();

// Execute and get bool result
$ok = $query->execute(['returnQuery' => false]);
Properties
PropertyTypeDescription
selectarraySELECT column expressions
fromarrayFROM table names
joinarrayJOIN clauses
leftjoinarrayLEFT JOIN clauses
wherearrayWHERE/AND conditions
orderbyarrayORDER BY expressions
groupbyarrayGROUP BY expressions
limitarrayLIMIT values
commentstringDebug comment
Query clauses

All clauses are available as fluent methods (inherited from DatabaseQuery.__call()):

select($columns, $params = [])

Add columns to the SELECT clause:

$query->select("id, name, status");
$query->select("count(*) AS total"); // append

from($table)

Add a table to the FROM clause. Tables are automatically backtick-quoted:

$query->from("pages");  // FROM `pages`
$query->from("pages_sortfields"); // adds second table

join($table, $params = [])

Add a JOIN clause:

$query->join("templates ON templates.id=pages.templates_id");

leftjoin($table, $params = [])

Add a LEFT JOIN:

$query->leftjoin("field_title ON field_title.pages_id=pages.id");

where($condition, $params = [])

Add a WHERE condition (first call) or AND condition (subsequent calls). Supports both named and implied bind parameters:

$query->where("status>?", 0);
$query->where("parent_id=:pid", [':pid' => 10]);

orderby($value, $prepend = false)

Add ORDER BY. Can be called multiple times. Pass true as second argument to prepend rather than append:

$query->orderby("name");          // ORDER BY name
$query->orderby("created DESC");  // ORDER BY name, created DESC
$query->orderby("priority", true); // ORDER BY priority, name, created DESC

groupby($columns)

Add GROUP BY. Supports HAVING as a shortcut:

$query->groupby("parent_id");
// HAVING can be added as a "column" starting with HAVING:
$query->groupby("HAVING count>1");

limit($limit)

Set the LIMIT clause:

$query->limit(25);      // LIMIT 25
$query->limit("0, 25"); // LIMIT 0,25
SQL caching

When $config->dbCache is false, SQL_NO_CACHE is prepended to the SELECT clause. This setting is static and shared across all instances.

Comments

Set a comment property to add a SQL comment (only in debug mode, as PDO misinterprets ? and :param patterns in comments):

$query->set('comment', 'Fetch homepage children');
Notes
  • DatabaseQuerySelectFulltext extends Wire, not DatabaseQuery. It decorates a DatabaseQuerySelect rather than extending it.
  • The constant maxQueryValueLength (500) limits search value length.
  • The class automatically handles stopwords, minimum word lengths, and MySQL fulltext index limitations.
  • Word alternates (singular/plural, lemmas) are generated via WireTextTools::getWordAlternates().
  • Boolean mode uses IN BOOLEAN MODE for word-level matching and scoring.
  • Query expansion uses WITH QUERY EXPANSION for related-word discovery.
  • The matchStartEnd() method uses RLIKE regex with support for ICU (MySQL 8+) and HenrySpencer regex engines.
  • Score fields are uniquely named to avoid conflicts when multiple fulltext queries are combined.
  • The $fieldName parameter of match() can be an array for searching across multiple columns 3.0.169.
match($tableName, $fieldName, $operator, $value)

The primary method. Updates the decorated query with the appropriate MATCH...AGAINST WHERE clause and ORDER BY score. This is called by Fieldtype modules and PageFinder.

Parameters:

  • $tableName (string): Database table name.
  • $fieldName (string): Column/field name (or array of names for multi-field search).
  • $operator (string): Search operator (see table below).
  • $value (string|int|array): Value to search for.

Supported operators

OperatorDescriptionMethod
*=Contains phrase (partial last word)matchPhrase
*+=Contains phrase with query expansionmatchPhraseExpand
**=Contains match (non-boolean scored)matchRegular
**+=Contains match with query expansionmatchRegular
^=Starts withmatchStartEnd
$=Ends withmatchStartEnd
~=Contains all full wordsmatchWords
~+=Contains all full words + expandmatchWords
~*=Contains all partial wordsmatchWords
~~=Contains all words live (partial last)matchWords
~\|=Contains any full wordsmatchWords
~\|*=Contains any partial wordsmatchWords
~\|+=Contains any words + expandmatchWords
~%=Contains all words LIKEmatchLikeWords
~\|%=Contains any words LIKEmatchLikeWords
%=Contains phrase LIKEmatchLikePhrase
%^=Starts with LIKEmatchLikeStartEnd
%$=Ends with LIKEmatchLikeStartEnd
#=Boolean mode commandsmatchCommands
=EqualsmatchEquals
!=Not equalsmatchEquals
> / < / >= / <=ComparisonmatchEquals

Negation

Prefix the operator with ! to negate the match (e.g., !*= for "does not contain phrase"):

$ft->match('field_body', 'data', '!~=', 'spam');
Configuration methods

allowOrder($allow = null)

Get or set whether ORDER BY score statements are added. When false, no ORDER BY is added (useful when the calling object will negate results):

$ft->allowOrder(false); // no ORDER BY score

allowStopwords($allow = null)

Get or set whether fulltext searches fallback to LIKE for stopwords. Default is true:

$ft->allowStopwords(false); // ignore stopwords completely

forceLike($forceLike = null)

Force LIKE-based matching for operators that have LIKE equivalents (*=, ^=, $=, ~=, ~|=):

$ft->forceLike(true);

getQuery()

Returns the DatabaseQuerySelect object being decorated:

$query = $ft->getQuery();
API reference: methods, properties, hooks

The intention behind these classes is to have a query that can safely be passed between methods and objects that add to it without knowledge of what other methods/objects have done to it. It also means being able to build a complex query without worrying about correct syntax placement.

This file is licensed under the MIT license

Below are Properties populated by DatabaseQuerySelect objects created by PageFinder. This is what gets passed to Fieldtype::getMatchQuery() method calls as properties available from the $query argument.


Click any linked item for full usage details and examples. Hookable methods are indicated with the icon. In addition to those shown below, the DatabaseQuerySelect class also inherits all the methods and properties of: DatabaseQuery, WireData and Wire.

Show class?     Show args?       Only hookable?    

Common

NameReturnSummary 
DatabaseQuerySelect::from($sql)
$this
Can also be used as property: DatabaseQuerySelect::from
DatabaseQuerySelect::getQuery()
None

Return the resulting SQL ready for execution with the database

 
DatabaseQuerySelect::groupby($sql)
$this
Can also be used as property: DatabaseQuerySelect::groupby
DatabaseQuerySelect::join($sql)
$this
Can also be used as property: DatabaseQuerySelect::join
DatabaseQuerySelect::leftjoin($sql)
$this
Can also be used as property: DatabaseQuerySelect::leftjoin
DatabaseQuerySelect::limit($sql)
$this
Can also be used as property: DatabaseQuerySelect::limit
DatabaseQuerySelect::orderby($value)
$this

Add an ORDER BY section to the query


Can also be used as property: DatabaseQuerySelect::orderby
 
DatabaseQuerySelect::select($sql)
$this
Can also be used as property: DatabaseQuerySelect::select
DatabaseQuerySelect::set($key, $value)
None 
DatabaseQuerySelect::where($sql)
$this
Can also be used as property: DatabaseQuerySelect::where

Properties

NameReturnSummary 
DatabaseQuerySelect::comment string Comments for query 
DatabaseQuerySelect::field Field Field object that is referenced by this query. 
DatabaseQuerySelect::group string Selector group (for OR-groups) if applicable. 
DatabaseQuerySelect::parentQuery DatabaseQuerySelect Parent query object, if applicable. 
DatabaseQuerySelect::selector Selector Selector object referenced by this query. 
DatabaseQuerySelect::selectors Selectors Original selectors (all) that $selector is part of.  

Additional methods and properties

In addition to the methods and properties above, DatabaseQuerySelect also inherits the methods and properties of these classes:

API reference based on ProcessWire core version 3.0.267