Klaus
, (*1)
User input interpreter for constructing SQL WHERE clause. Klaus can build complex WHERE clauses of variable depth and with different grouping conditions., (*2)
Documentation
Preparing Query
Raw query consists of the grouping operator definition (AND or OR) and condition. There are two types of conditions:, (*3)
Comparison Condition
Comparison consists of user input name, value and the comparison operator, e.g., (*4)
[
'name' => 'foo_name', // User input name
'value' => '1', // User input value
'operator' => '=' // Condition operator
]
Group Condition
The condition itself can define new group, e.g., (*5)
$query = [
'group' => 'AND',
'condition' => [
['name' => 'foo_name', 'value' => '1', 'operator' => '='],
['name' => 'bar_name', 'value' => '2', 'operator' => '='],
[
'group' => 'OR',
'condition' => [
['name' => 'foo_name', 'value' => '1', 'operator' => '='],
['name' => 'bar_name', 'value' => '2', 'operator' => '=']
]
]
]
]
A complete query must include at least one group and at least one comparison operator., (*6)
Mapping is used to restrict columns that can be included in the query, as well as to provide support for columns that depend on alias or even more complicated constructs., (*7)
SELECT
`f1`.`name`,
`b1`.`name`
FROM
`foo` `f1`
INNER JOIN
`bar` `b1`
ON
[..]
In the above example, you need to define relation between the parameter name that you are using in the query and the column name in the SQL query, e.g., (*8)
$map = [
'foo_name' => '`f1`.`name`',
'bar_name' => '`b1`.`name`'
];
Buildng the WHERE Clause
The preceeding examples explain how to prepare data for the Where constructor., (*9)
/**
* @param array $query
* @param array $map Map input name to the aliased column in the SQL query, e.g. ['name' => '`p1`.`name`'].
*/
$where = new \Gajus\Klaus\Where($query, $map);
We are going to use the SQL from the previous example to construct a prepared statement and execute it., (*10)
The WHERE clause itself is generated using getClause method:, (*11)
/**
* @return string SQL WHERE clause representng the query.
*/
$where->getClause();
If query does not produce a condition, then getClause will always return 1=1, e.g., (*12)
$sql = "
SELECT
`f1`.`name`,
`b1`.`name`
FROM
`foo` `f1`
INNER JOIN
`bar` `b1`
ON
[..]
WHERE
{$where->getClause()}
";
In the above example, $sql is:, (*13)
SELECT
`f1`.`name`,
`b1`.`name`
FROM
`foo` `f1`
INNER JOIN
`bar` `b1`
ON
[..]
WHERE
`f1`.`name` = :foo_name_0 AND
`b1`.`name` = :bar_name_1 AND
(
`f1`.`name` = :foo_name_2 OR
`b1`.`name` = :bar_name_3
)
To execute the query, you have to build PDOStatement, e.g., (*14)
$sth = $db->prepare($sql);
and execute it using the input data:, (*15)
/**
* @return array Input mapped to the prepared statement bindings present in the WHERE clause.
*/
$input = $where->getInput();
$sth->execute($input);
In the above example, $input is equal to:, (*16)
[
'foo_name_0' => '1',
'bar_name_1' => '2',
'foo_name_2' => '1',
'bar_name_3' => '2',
]
For basic search you can use Gajus\Klaus\Where::queryTemplate., (*17)
- Basic query template takes name => value pairs and converts them to
WHERE clause grouped using AND.
- Empty values are discarded.
- Values begning with
% will use LIKE comparison.
- Values endding with
% will use LIKE comparison.
- Values that do not contain
% or where % is not at the begining or end of the query will use = comparison.
Example
$query = \Gajus\Klaus\Where::queryTemplate(['foo' => 'bar', 'baz' => 'qux%']);
// $query is now eq. to:
$query = [
'group' => 'AND',
'condition' => [
['name' => 'foo', 'value' => 'bar', 'operator' => '='],
['name' => 'baz', 'value' => 'qux%', 'operator' => 'LIKE']
]
];
// Which you then pass to the Where constructor.
$where = new \Gajus\Klaus\Where($query, ['foo' => '`foo`', 'baz' => '`baz`']);
$sth = $db->prepare("SELECT `foo`, `baz` FROM `quux` WHERE {$where->getClause()}");
$sth->execute($where->getInput());
// ..
Alternatives
elasticsearch (ES) provides an API with a query DSL. The only downside of using ES is that it requires data dupliction., (*18)