sqltools/where

PHP7.1 流式、不可变 SQL 查询构建器。无连接、框架无关、无依赖。

1.4.2 2022-12-15 04:54 UTC

This package is auto-updated.

Last update: 2024-09-15 08:26:22 UTC


README

Latest Stable Version License Build Status Coverage Status Quality Score Total Downloads

Where

最简单的流畅 SQL 查询构建器。

使用 PHP7.1 构建,考虑不可变性。

特性

  • 框架无关,连接无关(你只需渲染一个字符串和一个值数组)
  • 自然语言:where、and、or...
  • 支持命名和数字占位符
  • 构建复杂、嵌套的 WHERE 条件
  • 构建 SELECT、INSERT、UPDATE、DELETE、REPLACE 查询的辅助函数
  • 构建 SQL 函数(如 IN、BETWEEN、IS NULL、CASE ... WHEN)的辅助函数

为什么?

在大多数情况下,简单的 SQL 查询就足够了。

但是,如果你的应用程序逻辑是以多个类/方法可以修改 SQL 查询的方式设计的(例如,像访问者模式),那么你可能需要一个查询构建器(例如,你可以在 WHERE 之前定义 LIMIT / OFFSET,查询将以正确的顺序渲染)。

条件构建器

Where 允许你使用 表达式 来构建你的条件。 表达式 是可以

  • 简单表达式: date_added = CURRENT_DATE
  • 复合表达式: date_added = CURRENT_DATE OR date_added = SUBDATE(CURRENT_DATE, INTERVAL 1 DAY)
  • 分组表达式: (country = 'UK' OR country = 'BE')
  • 否定表达式: NOT date_added = CURRENT_DATE

表达式 对象还可以包含一个参数数组以绑定(以避免 SQL 注入)。

你不需要实例化它们。只需依赖库提供的强大功能即可

require_once __DIR__ . '/vendor/autoload.php';

use function BenTools\Where\group;
use function BenTools\Where\not;
use function BenTools\Where\where;

$where = where('country IN (?, ?)', ['FRA', 'UK'])
    ->and(
        not(
            group(
                where('continent = ?', 'Europe')
                    ->or('population < ?', 100000)
            )
        )
    );

print((string) $where);
print_r($where->getValues());
print_r($where->preview());  // For debugging purposes

输出

country IN (?, ?) AND NOT (continent = ? OR population < ?)
Array
(
    [0] => FRA
    [1] => UK
    [2] => Europe
    [3] => 100000
)
country IN ('FRA', 'UK') AND NOT (continent = 'Europe' OR population < 100000)

每个 where()group()not() 函数都接受一个已实例化的 表达式 对象,或者一个字符串和一些可选参数。

$where = where('date > NOW()'); // valid
$where = where($where); // valid
$where = where(group($where)); // valid
$where = where(not($where)); // valid
$where = where('date = ?', date('Y-m-d')); // valid
$where = where('date BETWEEN ? AND ?', date('Y-m-d'), date('Y-m-d')); // valid
$where = where('date BETWEEN ? AND ?', [date('Y-m-d'), date('Y-m-d')]); // valid
$where = where('date BETWEEN :start AND :end', ['start' => date('Y-m-d'), 'end' => date('Y-m-d')]); // valid
$where = where('date BETWEEN :start AND :end', ['start' => date('Y-m-d')], ['end' => date('Y-m-d')]); // not valid
$where = where($where, date('Y-m-d'), date('Y-m-d')); // not valid (parameters already bound)

感谢流畅的接口,让您的 IDE 引导您完成其余部分。不要忘记 Where 总是不可变的:每次您进行更改时都要重新分配 $where

选择查询构建器

现在你已经学会了如何构建条件,你会发现构建整个选择查询就像小菜一碟

require_once __DIR__ . '/vendor/autoload.php';

use function BenTools\Where\group;
use function BenTools\Where\not;
use function BenTools\Where\select;
use function BenTools\Where\where;

$select = select('b.id', 'b.name  AS book_name', 'a.name AS author_name')
    ->from('books as b')
    ->innerJoin('authors as a', 'a.id = b.author_id')
    ->limit(10)
    ->orderBy('YEAR(b.published_at) DESC', 'MONTH(b.published_at) DESC', 'b.name')
    ->where(
        group(
            where('b.series = ?', 'Harry Potter')->or('b.series IN (?, ?)', ['A Song of Ice and Fire', 'Game of Thrones'])
        )
            ->and('b.published_at >= ?', new \DateTime('2010-01-01'))
        ->and(
            not('b.reviewed_at BETWEEN ? AND ?', new \DateTime('2016-01-01'), new \DateTime('2016-01-31 23:59:59'))
        )
    );
print_r((string) $select); // The SQL string
print_r($select->preview()); // For debugging purposes
SELECT b.id, b.name  AS book_name, a.name AS author_name 
FROM books as b 
INNER JOIN authors as a ON a.id = b.author_id 
WHERE (b.series = ? OR b.series IN (?, ?)) 
AND b.published_at >= ? 
AND NOT b.reviewed_at BETWEEN ? AND ? 
ORDER BY YEAR(b.published_at) DESC, MONTH(b.published_at) DESC, b.name 
LIMIT 10;
SELECT b.id, b.name  AS book_name, a.name AS author_name 
FROM books as b 
INNER JOIN authors as a ON a.id = b.author_id 
WHERE (b.series = 'Harry Potter' OR b.series IN ('A Song of Ice and Fire', 'Game of Thrones')) 
AND b.published_at >= '2010-01-01 00:00:00' 
AND NOT b.reviewed_at BETWEEN '2016-01-01 00:00:00' AND '2016-01-31 23:59:59' 
ORDER BY YEAR(b.published_at) DESC, MONTH(b.published_at) DESC, b.name 
LIMIT 10;

让您的首选 IDE 通过自动完成来完成其余部分。

RulerZ

Where 与出色的 RulerZ DSL 大多数兼容。

请确保对您的语句进行 group 以避免副作用。

示例

use function BenTools\Where\group;
use function BenTools\Where\not;

$fruits = [
    'banana',
    'apple',
];

$colors = [
    'yellow',
    'red',
];

$condition = group('fruit IN :fruits', ['fruits' => $fruits])->and(group('color IN :colors', ['colors' => $colors]));
$condition = not($condition);

var_dump($rulerz->satisfies(['fruit' => 'strawberry', 'color' => 'red'], (string) $condition, $condition->getValues())); // true
var_dump($rulerz->satisfies(['fruit' => 'apple', 'color' => 'yellow'], (string) $condition, $condition->getValues())); // false

安装

composer require bentools/where

测试

./vendor/bin/phpunit

另请参阅

bentools/simple-dbal - 一个 PHP 7.1+ 的 PDO & Mysqli 包装器。可以绑定 DateTime 参数。

bentools/pager - 一个 PHP 7.1+ 分页器。

bentools/flatten-iterator - 将多个 arrayTraversable 扁平化为一个迭代器。

bentools/etl - PHP7.1 ETL 模式实现。

latitude/latitude - 另一个 SQL 查询构建器,Where 是受其启发的。