smalldb/flupdo

Flupdo:一个简单且功能齐全的流式查询构建器

v1.4 2018-06-21 10:18 UTC

This package is auto-updated.

Last update: 2024-09-25 11:01:36 UTC


README

Flupdo是用PHP编写的简单SQL查询构建器。它设计得简单、确定、透明且易于使用。Flupdo不包含任何通常在出现小错误时难以预测的智能逻辑。

Flupdo支持(或应支持)100%的MySQL语法。Sqlite和SphinxQL也得到支持,但未经过良好测试。计划支持PostgreSQL,可能只需要进行一些小的调整,因此可能已经可以使用。

Flupdo基于PDO构建。它不替换fetch方法或任何其他PDO API,它只添加了几个构建方法,这些方法创建查询构建器对象,从而保持与PDO的完全兼容性。当执行查询时,将返回普通的PDOStatement实例。

Flupdo支持位置和命名占位符,但不能混用。位置占位符在将值与SQL语句一起传递给查询构建器时很有用(请参阅“基本用法”部分)。命名占位符用于预处理查询,其中所有值一次性传递(请参阅“预处理查询”部分)。

Flupdo使用PHPT进行测试,这是PHP本身使用的工具。请参阅“test”目录。

Flupdo使用Doxygen进行文档编写 -- make doc 就可以了。

Flupdo不提供构建常见查询的智能构造和辅助工具。这些功能超出了Flupdo的范围。Flupdo旨在成为一个基本工具,用于由这些辅助工具和智能查询构建器使用来拼接查询。因此,如果您需要更智能的功能,请在其之上构建。例如,Smalldb就是这样一种框架。

有关更多详细信息,请参阅项目网站: https://smalldb.org/

基本用法

所有构建方法都接受SQL片段作为第一个参数,参数作为任何其他参数。例如

$q->where('id = ?', $id);

它将在WHERE子句中添加条件 (id = ?) 并将 $id 添加到参数列表中。因此,整个查询将如下所示

SELECT ...
WHERE ... AND (id = ?)

要执行查询,您可以使用 query() 或 exec() 方法。它们具有与 PDO::query() 和 PDO::exec() 相同的语义,但它们不接受任何参数,因为查询已经包含在查询构建器中。例如,要执行上述查询,请使用此方法

$pdostmt = $q->query();

然后可以像往常一样检索结果

print_r($pdostmt->fetchAll(PDO::FETCH_ASSOC));

预处理查询

当查询需要为多次使用进行预处理时,最好使用命名占位符

$pdostmt = $q->insert()->into('users')
        ->set('name = :name')
        ->set('password = :password')
        ->prepare();

然后可以轻松地重复执行

$flupdo->beginTransaction();
foreach ($users as $u) {
    $pdostmt->execute(array('name' => $u['name'], 'password' => $u['password']));
}
$flupdo->commit();

子查询

可以逐字将简短子查询传递给任何构建方法

$q->select('(SELECT MAX(`id`) + 1 FROM users) AS `next_id`');

更复杂的查询应由Flupdo构建,并通过数组作为第一个参数传递给构建方法

$q2 = $flupdo->select('MAX(`id`) + 1')->from('users');
$q->select(array($q2, 'AS `next_id`'));

这两个示例将生成相同的SELECT语句。

警告:在子查询之前不允许使用位置占位符

$q->where(array($subquery, ' > ?'), $n); // Good
$q->where(array('n + ? IN ', $subquery), $c); // Bad

构建方法

构建方法与转换为小骆驼式的SQL关键字同名

  • select(), where(), from(), join(), leftJoin(), innerJoin(), orderBy(), groupBy(), having(), ...
  • distinct(), highPriority(), sqlNoCache(), ...

还有所有查询类型中都可用的注释方法 headerComment() 和 footerComment()。它们在SQL查询前后添加简单的注释。这些可能很有用,可以标记查询在代码中的位置,以便从慢查询日志中轻松找到查询

$q->footerComment(__FILE__.':'.__LINE__);

复杂连接

请注意,连接被视为独立子句,而不是FROM子句的一部分。这意味着不可能进行复杂连接,但简单的多个连接链很容易。要构建复杂的FROM子句,请将FROM子句逐字指定为单个 from() 调用

$q->from('t1, (t2, t3), t4');

这也意味着,这段代码

$q->from('t1');
$q->join('t2 ...');
$q->from('t3');

... 将生成以下SQL查询

SELECT ...
FROM t1, t3
JOIN t2 ...

这种行为是有意为之的,因为它简化了复杂过滤查询的构建。

内部逻辑

Flupdo的内部逻辑非常简单,但功能强大。它只包含少量缓冲区,用于存储构建方法调用。在查询执行之前,根据查询需要,通过正确排序这些缓冲区的内容(使用正确的连接词和关键词)来编译最终查询。

第一个构建方法调用(在Flupdo实例上)确定查询的类型,并返回FlupdoBuilder子类的实例。之后无法更改查询的类型。

Flupdo不会解析也不会理解SQL片段。它只使用字符串级别的连接。如果需要更复杂的行为,可以在Flupdo之上编写额外的辅助方法或更高级的查询构建器。

示例

这些示例可以作为test目录中的测试使用。

初始化

$flupdo = new Flupdo($dsn, $username, $password); // Same as PDO.

简单的选择

$q = $flupdo->select('n AS TheNumber')
        ->select('n + 1')
        ->distinct()
        ->select('n + 2')
        ->headerComment('Simple select')
        ->from('numbers')
        ->where('n > ?', 5)
        ->where('n < ?', 200)
        ->orderBy('n DESC');

查询结果与Flupdo生成的完全一致(包括空白字符)

    -- Simple select
    SELECT DISTINCT n AS TheNumber,
            n + 1,
            n + 2
    FROM numbers
    WHERE (n > ?)
            AND (n < ?)
    ORDER BY n DESC

带有子查询的更复杂示例

$q = $flupdo->select('n')
        ->from('numbers')
        ->where(array('n >', $flupdo->select('MIN(n) + ?', 2)->from('numbers')))
        ->where('n < ?', 100)
        ->orderBy('n DESC');

查询结果与Flupdo生成的完全一致(包括空白字符)

    SELECT n
    FROM numbers
    WHERE (n > (
                    SELECT MIN(n) + ?
                    FROM numbers
            ))
            AND (n < ?)
    ORDER BY n DESC

文档

请参阅https://smalldb.org/doc/flupdo/master/

许可证

大部分代码在Apache 2.0许可证下发布。有关详细信息,请参阅LICENSE文件。

贡献指南

项目的主要仓库托管在https://git.frozen-doe.net/smalldb/flupdo,您可以在此处提交问题或创建合并请求。