everon/criteria-builder

Everon 条件构建组件

3.0.0 2021-06-04 16:21 UTC

This package is auto-updated.

Last update: 2024-09-05 15:54:04 UTC


README

生成完整的 SQL WHERE 语句的库,具有简单、流畅和直观的界面。

版本

  • 使用 v1.x 和 v2.x 与 PHP 7.2+
  • 使用 v3.x 与 PHP 8+

功能

  • 它不是 DQL
  • 重要的 SQL,无聊事物的流畅界面
  • 自动 PDO 参数名转义和唯一性,自定义参数
  • 流畅界面
  • 轻松创建多个条件
  • 几乎 20 个可用的运算符
  • 轻松扩展自定义运算符
  • 直观界面:清晰、小巧、简单的 API
  • 干净的代码

没有无聊的 SQL

关注重要的事

您可以通过 CriteriaBuilder->sql($sql) 添加自己的 SQL,并以简单灵活的方式生成快速的 SQL 查询,无需处理无聊的字符串连接、代码重复以及大量与 LIMITOFFSETSORT 语句相关的 if/else、switch 语句或常量。所有这些无聊的部分都被 CriteriaBuilderInterface 消除了。

当你需要螺丝刀时,锤子是不会做的

把无聊的东西放在一边,你可以完全控制 SQL 的构建方式,这对于高度复杂、复杂或非常具体的查询非常有用,在这些查询中使用 DQL 实际上比使用它更容易。DQL 对于日常使用来说很棒,但有时你需要非常具体地表达自己,而原始的 SQL 是到达那里的最佳方式。

将请求翻译成数据库可以理解的内容

使用 Operatorswhere 语句和 setLimitsetOffsetsetOrderBy 等方法轻松将请求参数翻译成数据库可以理解的内容。例如,对于分页或筛选非常有用。

SQLSQL 参数 和应用聚合、排序或限制等概念之间进行清晰的分离。现在您只需要关注最重要的部分,即 SQL 部分。

由于 SqlPartInterface,与 PDO 一起使用非常简单

$sth = $dbh->prepare($SqlPart->getSql());
$sth->execute($SqlPart->getParameters());

示例

简单查询

$CriteriaBuilder
    ->where('id', '=', 123)

将被转换为

WHERE (id = :id_843451772)

带有参数

array(8) [
  'id_843451772' => integer 123
]

Where、orWhere 和 andWhere

每个 where 语句都会创建一个新的容器,其中包含 Criteria 对象。Criteria 对象包含一系列 Criterium 对象。Criterium 是一个条件。

您可以通过使用 andWhereorWhere 方法来附加 Criterium。

每次使用 where 语句时,都会创建一个新的 Criteria,准备好新的一组条件。

$CriteriaBuilder
    ->where('id', 'IN', [1,2,3])
        ->orWhere('id', 'NOT IN', [4,5,6])
        ->andWhere('name', '=', 'foo');
    ->where('modified', 'IS', null)
        ->andWhere('name', '!=', null)
        ->orWhere('id', '=', 55);

将被转换为

WHERE (
    id IN (:id_843451778,:id_897328169,:id_1377365551)
    OR id NOT IN (:id_1260952006,:id_519145813,:id_1367241593)
    AND name = :name_1178871152
)
AND (
    modified IS NULL
    AND name IS NOT NULL
    OR id = :id_895877163
)

带有参数

array(8) [
  'name_1178871152' => string (3) "foo"
  'id_1260952006' => integer 4
  'id_519145813' => integer 5
  'id_1367241593' => integer 6
  'id_843451778' => integer 1
  'id_897328169' => integer 2
  'id_1377365551' => integer 3
  'id_895877163' => integer 55

要使用 OR 操作符连接 Criteria,请使用 glueByOr 方法。

$CriteriaBuilder
    ->where('id', 'IN', [1,2,3])
        ->orWhere('id', 'NOT IN', [4,5,6])
        ->andWhere('name', '=', 'foo');
    ->glueByOr()
    ->where('modified', 'IS', null)
        ->andWhere('name', '!=', null)
        ->orWhere('id', '=', 55);

将被转换为

WHERE (
    id IN (:id_843451778,:id_897328169,:id_1377365551)
    OR id NOT IN (:id_1260952006,:id_519145813,:id_1367241593)
    AND name = :name_1178871152
)
OR (
    modified IS NULL
    AND name IS NOT NULL
    OR id = :id_895877163
)

原始 SQL

使用 whereRaw 方法轻松实现原始 SQL。

$CriteriaBuilder
    ->whereRaw('foo + bar')
    ->andWhereRaw('1=1')
    ->orWhereRaw('foo::bar()');

将被转换为

WHERE (foo + bar AND 1=1 OR foo::bar())

Group By

使用 setGroupBy 方法轻松使用 Group By。

$CriteriaBuilder
    ->where('name', '!=', 'foo')
        ->andWhere('id', '=', 123)
    ->setGroupBy('name,id');

将被转换为

WHERE (name != :name_1178871154 AND id = :id_897328160)
GROUP BY name,id

带有参数

array(8) [
  'name_1178871154' => string (3) "foo"
  'id_897328160' => integer 123
]

Limit 和 Offset

使用 setLimitsetOffset 方法非常直接。

$CriteriaBuilder
    ->whereRaw('foo + bar')
        ->andWhereRaw('1=1')
        ->orWhereRaw('foo::bar()');
    ->setLimit(10)
    ->setOffset(5);

将被转换为

WHERE (foo + bar AND 1=1 OR foo::bar())
LIMIT 10 OFFSET 5

Order By

使用 ASCDESC 关键字以及 setOrderBy 方法实现的关联数组实现 Order By。

$CriteriaBuilder
    ->whereRaw('foo + bar')
        ->andWhereRaw('1=1')
        ->orWhereRaw('foo::bar()')
    ->setOrderBy([
        'name' => 'DESC',
        'id' => 'ASC'
    ]);

将被转换为

WHERE (foo + bar AND 1=1 OR foo::bar())
ORDER BY name DESC,id ASC

自定义连接

还可以通过使用 glue 方法手动处理 Criteria。

$CriteriaBuilder
        ->where('id', 'IN', [1,2,3])
        ->orWhere('id', 'NOT IN', [4,5,6])
    ->glueByOr()
        ->where('name', '!=', 'foo')
        ->andWhere('email', '!=', 'foo@bar')
    ->glueByAnd()
        ->where('bar', '=', 'bar')
        ->andWhere('name', '=', 'Doe');

$CriteriaBuilder->setLimit(10);
$CriteriaBuilder->setOffset(5);
$CriteriaBuilder->setGroupBy('name,id');
$CriteriaBuilder->setOrderBy(['name' => 'DESC', 'id' => 'ASC']);

将被转换为

(id IN (:id_1263450107,:id_1088910886,:id_404821955) OR id NOT IN (:id_470739703,:id_562547487,:id_230395754))
OR (name != :name_1409254675 AND email != :name_190021050)
AND (bar = :bar_1337676982 AND name = :name_391340793)
GROUP BY name,id
ORDER BY name DESC,id ASC
LIMIT 10 OFFSET 5

带有参数

array(10) [
    'id_470739703' => integer 4
    'id_562547487' => integer 5
    'id_230395754' => integer 6
    'id_1263450107' => integer 1
    'id_1088910886' => integer 2
    'id_404821955' => integer 3
    'name_190021050' => string (3) "foo@bar"
    'name_1409254675' => string (3) "foo"
    'name_391340793' => string (3) "Doe"
    'bar_1337676982' => string (3) "bar"
]

运算符

有大约 20 个可用的运算符,如 Equal、NotIn、Between 或 Is。 查看所有运算符

Equal

$CriteriaBuilder->where('foo', '=', 'bar');

将输出

WHERE (foo = :foo_1337676681)

NotIn

$CriteriaBuilder->where('foo', 'NOT IN', ['bar', 'buzz']);

将输出

WHERE (foo NOT IN [:foo_1337676681, :foo_1337776681)

Between

必须提供 exactly 2 个参数,否则将抛出异常。

$CriteriaBuilder->where('foo', 'BETWEEN', ['bar', 'buzz']);

将输出

WHERE (foo BETWEEN :foo_1337676681 AND :foo_1337776681)

还有很多其他选项。请在此处查看更多示例

自定义运算符

您可以使用以下方式注册自己的运算符

/**
 * @param $sql_type
 * @param $operator_class_name
 *
 * @return void
 */
public static function registerOperator($sql_type, $operator_class_name);

例如

class OperatorCustomTypeStub extends AbstractOperator
{
    const TYPE_NAME = 'CustomType';
    const TYPE_AS_SQL = '<sql for custom operator>';
}

Builder::registerOperator(OperatorCustomTypeStub::TYPE_AS_SQL, 'Some\Namespace\OperatorCustomTypeStub');

您可以使用自己的运算符与 raw 方法一起使用。

$CriteriaBuilder->whereRaw('bar', null, OperatorCustomTypeStub::TYPE_AS_SQL);
$CriteriaBuilder->andWhereRaw('foo', ['foo' => 'bar'], OperatorCustomTypeStub::TYPE_AS_SQL);
$CriteriaBuilder->orWhereRaw('foo', 'bar', OperatorCustomTypeStub::TYPE_AS_SQL);

将输出

WHERE (bar <sql for custom operator> NULL AND foo <sql for custom operator> :foo_1337676981
    OR foo <sql for custom operator> :foo_2137676760 )

请访问https://github.com/oliwierptak/everon-criteria-builder/tree/development/src/Operator 了解更多示例

使用方法

依赖注入通过 Everon Factory 完成。

使用 CriteriaBuilderFactoryWorker->buildCriteriaBuilder() 初始化。

use Everon\Component\CriteriaBuilder\CriteriaBuilderFactoryWorkerInterface;
use Everon\Component\Factory\Dependency\Container;
use Everon\Component\Factory\Factory;

include('vendor/autoload.php');

$Container = new Container();
$Factory = new Factory($Container);
$Factory->registerWorkerCallback('CriteriaBuilderFactoryWorker', function() use ($Factory) {
    return $Factory->buildWorker(CriteriaBuilderFactoryWorker::class);
});

$CriteriaBuilderFactoryWorker = $Factory->getWorkerByName('CriteriaBuilderFactoryWorker');
$CriteriaBuilder = $CriteriaBuilderFactoryWorker->buildCriteriaBuilder();

设置您的条件。

$CriteriaBuilder
        ->where('sku', 'LIKE', '13%')
        ->orWhere('id', 'IN', [1, 2, 3])
    ->glueByOr()
        ->where('created_at', '>', '2015-12-03 12:27:22');

将条件字符串追加到现有的 SQL 中。

$sql = 'SELECT * FROM <TABLE>';
$sql = $sql . (string) $CriteriaBuilder;
$sth = $dbh->prepare($sql);

获取示例数据。在将 SQL 添加到 CriteriaBuilder 之后,使用 SqlPartInterface 及其如 getSqlgetParameters 等方法检索 SQL 查询 和其 参数 更加容易。

$dbh = new \PDO('mysql:host=127.0.0.1;dbname=DATABASE', 'root', '');
$SqlPart = $CriteriaBuilder->toSqlPart();
$sth = $dbh->prepare($SqlPart->getSql());
$sth->execute($SqlPart->getParameters());

整合所有内容

$dbh = new \PDO('mysql:host=127.0.0.1;dbname=DATABASE', 'root', '');
$CriteriaBuilder
    ->sql('SELECT * FROM fooTable f LEFT JOIN barTable b ON f.bar_id = b.id AND f.is_active = :is_active')
    ->where('bar', '=', 1)
        ->andWhere('foo', 'NOT IN', [1,2,3])
        ->orWhereRaw('foo::bar() IS NULL')
    ->setParameter('is_active', false)
    ->setLimit(10)
    ->setOffset(20)
    ->setOrderBy(['foo' => 'DESC']);

$SqlPart = $CriteriaBuilder->toSqlPart();
$sth = $dbh->prepare($SqlPart->getSql());
$sth->execute($SqlPart->getParameters());
$data = $sth->fetchAll(PDO::FETCH_ASSOC);

测试驱动

请在此处检查更多使用示例的测试