zlikavac32/query-builder

SQL查询构建库,它不是从头开始构建SQL查询,而是修改现有的查询。

dev-master 2020-04-18 00:16 UTC

This package is auto-updated.

Last update: 2024-09-18 09:56:46 UTC


README

Build Status Latest Stable Version License

SQL查询构建库,它不是从头开始构建SQL查询,而是修改现有的查询。

目录

  1. 介绍
  2. 工作原理
  3. 安装
  4. 配置
    1. 预加载
  5. 用法
    1. 子查询内联
  6. 限制

介绍

如何在PHP和数据库之间实现和谐一直是许多博客文章的主题。虽然有些人提出并使用各种ORM,如Doctrine和Eloquent,但其他人坚持使用原始SQL查询。ORM带有某种查询构建器,这非常有用。例如,当向管理页面提供筛选时,程序化修改查询以反映请求的筛选很有用。

如果我们考虑查询本身,真正需要从头构建查询的情况非常罕见(我自己从未遇到过)。我们通常有一个基础查询做某件事,然后扩展它。在上面的筛选示例中,我们可以有 SELECT t.id, t.name FROM tickets t WHERE t.date >= '2020-01-01 作为今年票的基础查询,然后有一个针对 state 的筛选,将初始查询修改为 SELECT t.id, t.name FROM tickets t WHERE t.date > '2020-01-01' AND t.state = 'SOLD'

这就是这个查询构建器背后的主要前提。重用现有查询,而不是通过查询构建器手动构建完整查询。

它是如何工作的?

每个 SELECT 语句都被分解为类似于 columnswhere 的部分,然后可以通过公开的查询构建器API修改该语句。为了使其成为可能,查询构建器解析语句并跟踪所有参数占位符及其参数值,当修改某个部分时,参数也会合并/删除。

这意味着在将该部分添加到查询构建器时必须知道参数,无论是初始查询还是某个新的部分。换句话说,这个查询构建器并不打算用于可重用的预处理语句(目前还不是!)。

使用的解析器是一个 小的SQL解析器,用C编写并通过FFI公开(将来可能会有更多的解析器实现)。

安装

建议通过Composer安装。

composer require zlikavac32/query-builder

配置

要使用查询构建器,创建一个查询构建器环境。

use Zlikavac32\QueryBuilder\FFISqlParser;
use Zlikavac32\QueryBuilder\NonPreloadedFFIGateway;
use Zlikavac32\QueryBuilder\ParserBackedQueryEnvironment;

$parser = NonPreloadedFFIGateway::createDefault();
$parser = new FFISqlParser($parser);
$queryBuilder = new ParserBackedQueryEnvironment($parser);

预加载

您不需要在需要时导入FFI定义,FFI定义可以被预加载。没有漂亮或自动的方法来做这件事。在您的预加载脚本中,应该添加

FFI::load('{{path}}');

其中 {{path}} 代表此存储库中 tsqlp.h 头文件的路劲,例如 __DIR__ . '/vendor/zlikavac32/query-builder/tsqlp.h'。其他(可能必要的)选项是使用 ffi.preload 并带有 tsqlp.h 的路径。有关更多信息,请参阅 FFI配置

另一个变化是您不能再使用 \Zlikavac32\QueryBuilder\NonPreloadedFFIGateway 类,而应该使用 \Zlikavac32\QueryBuilder\PreloadedFFIGateway 类。

用法

使用构造的环境从 SQL 字符串或 \Zlikavac32\QueryBuilder\Query 实例创建查询构建器。

$qb = $queryBuilder->queryBuilderFromString(
    'SELECT * FROM user WHERE active = ?', 
    1
);

$qb->andWhere('registered_at > ?', '2020-01-01');

$query = $qb->build();

var_dump($query->sql(), $query->parameters());
// SELECT * FROM user WHERE (active = ?) AND (registered_at > ?)
// [1, '2020-01-01']

有关可用查询构建器方法的更多信息,请查看 \Zlikavac32\QueryBuilder\QueryBuilder

子查询内联

由于这个库可以解析查询,它可以将子查询注入到参数占位符中。

use Zlikavac32\QueryBuilder\Query;

$userOfTheLatestTransactionQuery = Query::create(
    'SELECT user_id FROM transaction ORDER BY created_at DESC LIMIT 1'
);
$qb = $queryBuilder->queryBuilderFromString(
    'SELECT * FROM user WHERE id = ?', 
    $userOfTheLatestTransactionQuery
);

$query = $qb->build();

var_dump($query->sql(), $query->parameters());
// SELECT * FROM user WHERE id = (SELECT user_id FROM transaction ORDER BY date DESC LIMIT 1)
// []

限制

使用的解析器可能会(很可能也会)将某些SQL查询解析为仅对它们有效的查询,然后从数据库中拒绝。这是出于设计考虑,以保持解析简单,因为该解析器并不打算用作代码检查器或其他工具。它甚至不会生成AST,生成的查询将立即执行,因此逻辑错误将立即被发现。查询构建器本身不会将有效的查询生成无效查询。这并不是一个限制,但提到这一点是有用的。