cloud-castle/query-builder

Production-ready PHP 8.1+ package (CloudCastle QueryBuilder).

Maintainers

Package info

gitverse.ru/cloud-castle/query-builder

Homepage

Issues

Documentation

pkg:composer/cloud-castle/query-builder

Transparency log

Statistics

Installs: 10

Dependents: 4

Suggesters: 0

v0.1.1 2026-07-17 20:55 UTC

README

🇷🇺 Русский · 🇬🇧 English · 🇩🇪 Deutsch · 🇫🇷 Français · 🇪🇸 Español · 🇮🇹 Italiano

CloudCastle QueryBuilder

CloudCastle QueryBuilder

Иммутабельный, типобезопасный, кросс-диалектный конструктор SQL-запросов для PHP 8.1+. Строит запросы любой сложности и вложенности для максимально широкого спектра СУБД, генерируя безопасный SQL с плейсхолдерами. Библиотека не исполняет запросы — она их корректно порождает.

Packagist Version Downloads PHP Version License

GitVerse

PHPStan Psalm PHPMD PHPCS Coverage Infection MSI

Ключевые особенности

  • Иммутабельность — каждый вызов возвращает новый строитель; базовый запрос безопасно переиспользуется и ветвится.
  • Типобезопасность — строгая типизация, полные PHPDoc-типы, проверка PHPStan (max) и Psalm.
  • Только параметризованные запросы — значения никогда не попадают в текст SQL; идентификаторы квотируются по правилам диалекта. Защита от инъекций на уровне архитектуры.
  • 56 диалектов — реляционные, NewSQL, колоночные/OLAP, встраиваемые, time-series, wide-column, search, streaming, federated, графовые, multi-model, vector.
  • Fail-safe контракт — при отсутствии нативной конструкции библиотека либо генерирует семантически эквивалентную эмуляцию, либо явно и безопасно отказывает; никогда не порождает молча запрос, возвращающий другой результат.
  • Один AST — любой диалект — смена целевой СУБД без пересборки запроса.

Установка

composer require cloud-castle/query-builder

Требуется PHP 8.1+.

Быстрый старт

<?php

use CloudCastle\QueryBuilder\Query;
use CloudCastle\QueryBuilder\Expr;
use CloudCastle\QueryBuilder\Grammar\PostgresDialect;

$query = Query::select('u.id', 'u.email', Expr::alias(Expr::count('orders.id'), 'orders_count'))
    ->from('users', 'u')
    ->leftJoin('orders', 'orders.user_id', 'u.id')
    ->where('u.status', '=', 'active')
    ->groupBy('u.id', 'u.email')
    ->having('orders_count', '>', 5)
    ->orderBy('orders_count', OrderDirection::Desc)
    ->limit(50);

$compiled = $query->toCompiled(new PostgresDialect());

// SELECT "u"."id", "u"."email", COUNT("orders"."id") AS "orders_count" FROM "users" AS "u"
//   LEFT JOIN "orders" ON "orders"."user_id" = "u"."id" WHERE "u"."status" = $1
//   GROUP BY "u"."id", "u"."email" HAVING "orders_count" > $2 ORDER BY "orders_count" DESC LIMIT 50
$compiled->sql();
$compiled->bindings(); // ['active', 5]

Тот же AST компилируется под другой диалект без пересборки:

$query->toCompiled(new MySqlDialect())->sql();  // тот же запрос в лексике MySQL

Возможности

КатегорияЧто поддерживается
DMLSELECT (подзапросы любой вложенности, CTE + рекурсивные + MATERIALIZED, оконные функции + рамки + именованные WINDOW, QUALIFY, GROUPING SETS/ROLLUP/CUBE, DISTINCT ON, LATERAL, FILTER, блокировки FOR UPDATE/SKIP LOCKED), INSERT (+DEFAULT VALUES, upsert, INSERT SELECT), UPDATE, DELETE, MERGE, UNION/INTERSECT/EXCEPT, VALUES-источник, PIVOT/UNPIVOT, TABLESAMPLE
ВыраженияФасад Expr + 15 категорий Fn\* (~153 метода): строковые, математические, дата/время, агрегаты, JSON, условные, оконные, приведения, массивы, гео (PostGIS), regexp, кодирование, сеть, побитовые, системные. Любая функция — через Expr::func()
DDLCREATE/ALTER/DROP TABLE, CREATE/DROP INDEX/VIEW/SCHEMA/SEQUENCE, CREATE TABLE AS SELECT, TRUNCATE, ENUM-колонки, внешние ключи, комментарии
DCLGRANT/REVOKE, CREATE/DROP ROLE, COMMENT ON
TCLBEGIN/COMMIT/ROLLBACK, SAVEPOINT, уровни изоляции
ИнтроспекцияCatalog: таблицы, колонки, представления, ограничения, схемы, подпрограммы, триггеры через INFORMATION_SCHEMA
ПрочееCALL процедур, EXPLAIN [ANALYZE], графовые языки (Cypher, SQL/PGQ), streaming (ksqlDB, Flink), векторный поиск

Fail-safe контракт

Для каждой возможности стратегия выбирается по порядку:

  1. native — нативная конструкция диалекта.
  2. emulated — семантически эквивалентная эмуляция, дающая тот же результат (например, NULLS FIRST/LAST через CASE).
  3. degraded — приблизительная эмуляция; разрешена только в режиме lenient с регистрацией предупреждения.
  4. unsupported — типизированное исключение UnsupportedCapabilityException с указанием возможности, диалекта и альтернативы.
use CloudCastle\QueryBuilder\Enum\CompilationMode;

// strict (по умолчанию): отказ при приблизительной эмуляции и отсутствии поддержки
$query->toCompiled($dialect);

// lenient: приблизительная эмуляция разрешена, предупреждения — в CompiledQuery::warnings()
$query->toCompiled($dialect, CompilationMode::Lenient);

Безопасность

  • Только параметризованные запросы — значения передаются отдельно от текста SQL.
  • Идентификаторы, алиасы и направления сортировки экранируются/квотируются по правилам диалекта.
  • Имена функций, типов и полей проходят белый список символов.
  • Библиотека не логирует значения привязок по умолчанию (потенциальные ПД/финданные).

Диалекты

56 драйверов, среди них PostgreSQL, MySQL, MariaDB, Oracle, SQL Server, SQLite, DuckDB, ClickHouse, Snowflake, BigQuery, Redshift, CockroachDB, YugabyteDB, TiDB, Spanner, Trino, Spark SQL, TimescaleDB, QuestDB, Cassandra (CQL), ksqlDB, Flink SQL, Neo4j (Cypher) и другие.

Качество

  • 569 тестов, покрытие строк 100%, Mutation Score Indicator (MSI) 100%.
  • Прогон анализаторов: phplint → Psalm → PHPStan (max) → PHPMD → PHPCS → Rector → Deptrac → Infection.
  • PHP 8.1–8.5.

Разработка

composer install
composer check    # линтеры + статический анализ + тесты
composer fix      # автоисправления (Rector, PHP CS Fixer, PHPCBF)
composer ci       # полный CI-пайплайн локально

Документация

Лицензия

MIT © CloudCastle (alex-4-17@yandex.ru)

🇷🇺 Русский · 🇬🇧 English · 🇩🇪 Deutsch · 🇫🇷 Français · 🇪🇸 Español · 🇮🇹 Italiano