gajus/klaus

用户输入解释器,用于构建 SQL WHERE 子句。

0.1.0 2014-04-25 15:55 UTC

This package is not auto-updated.

Last update: 2024-09-14 14:11:11 UTC


README

Build Status Coverage Status Latest Stable Version License

用户输入解释器,用于构建 SQL WHERE 子句。Klaus 可以构建具有不同分组条件的复杂深度的 WHERE 子句。

文档

准备查询

原始查询由分组运算符定义(ANDOR)和条件组成。有两种类型的条件

比较条件

比较由用户输入名称、值和比较运算符组成,例如。

[
    'name' => 'foo_name', // User input name
    'value' => '1', // User input value
    'operator' => '=' // Condition operator
]

分组条件

条件本身可以定义新分组,例如。

$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' => '=']
            ]
        ]
    ]
]

完整的查询必须至少包含一个分组和一个比较运算符。

使用输入映射

映射用于限制可以包含在查询中的列,以及为依赖于别名或更复杂结构的列提供支持。

SELECT
    `f1`.`name`,
    `b1`.`name`
FROM
    `foo` `f1`
INNER JOIN
    `bar` `b1`
ON
    [..]

在上面的示例中,您需要定义查询中使用的参数名称与 SQL 查询中的列名称之间的关系,例如。

$map = [
    'foo_name' => '`f1`.`name`',
    'bar_name' => '`b1`.`name`'
];

构建 WHERE 子句

前面的示例解释了如何为 Where 构造函数准备数据。

/**
 * @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);

我们将使用前面的示例中的 SQL 构建一个预处理语句并执行它。

使用 getClause 方法生成 WHERE 子句本身

/**
 * @return string SQL WHERE clause representng the query.
 */
$where->getClause();

如果查询不生成条件,则 getClause 将始终返回 1=1,例如。

$sql = "
SELECT
    `f1`.`name`,
    `b1`.`name`
FROM
    `foo` `f1`
INNER JOIN
    `bar` `b1`
ON
    [..]
WHERE
    {$where->getClause()}
    ";

在上面的示例中,$sql

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
        )

要执行查询,您必须构建 PDOStatement,例如。

$sth = $db->prepare($sql);

并使用输入数据执行它

/**
 * @return array Input mapped to the prepared statement bindings present in the WHERE clause.
 */
$input = $where->getInput();

$sth->execute($input);

在上面的示例中,$input 等于

[
    'foo_name_0' => '1',
    'bar_name_1' => '2',
    'foo_name_2' => '1',
    'bar_name_3' => '2',
]

输入模板

对于基本搜索,您可以使用 Gajus\Klaus\Where::queryTemplate

  • 基本查询模板采用名称 => 值对,并将它们转换为使用 AND 分组的 WHERE 子句。
  • 空值将被忽略。
  • % 开头的值将使用 LIKE 比较运算符。
  • % 结尾的值将使用 LIKE 比较运算符。
  • 不包含 %% 不是查询开头或结尾的值将使用 = 比较运算符。

示例

$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());

// ..

替代方案

elasticsearch (ES) 提供了一个具有查询 DSL 的 API。使用 ES 的唯一缺点是需要数据复制。