everon / criteria-builder
Everon 条件构建组件
Requires
- php: ^8
- everon/collection: ^3
- everon/factory: ^3
- everon/utils: ^3
Requires (Dev)
- mockery/mockery: ^1
- phpunit/phpunit: ^9
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 查询,无需处理无聊的字符串连接、代码重复以及大量与 LIMIT、OFFSET 或 SORT 语句相关的 if/else、switch 语句或常量。所有这些无聊的部分都被 CriteriaBuilderInterface
消除了。
当你需要螺丝刀时,锤子是不会做的
把无聊的东西放在一边,你可以完全控制 SQL 的构建方式,这对于高度复杂、复杂或非常具体的查询非常有用,在这些查询中使用 DQL 实际上比使用它更容易。DQL 对于日常使用来说很棒,但有时你需要非常具体地表达自己,而原始的 SQL
是到达那里的最佳方式。
将请求翻译成数据库可以理解的内容
使用 Operators
、where
语句和 setLimit
、setOffset
或 setOrderBy
等方法轻松将请求参数翻译成数据库可以理解的内容。例如,对于分页或筛选非常有用。
在 SQL
、SQL 参数
和应用聚合、排序或限制等概念之间进行清晰的分离。现在您只需要关注最重要的部分,即 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 是一个条件。
您可以通过使用 andWhere
和 orWhere
方法来附加 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
使用 setLimit
和 setOffset
方法非常直接。
$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
使用 ASC
和 DESC
关键字以及 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
及其如 getSql
和 getParameters
等方法检索 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);