ddbase3 / php-struql
A PHP implementation of the Struql query language โ parse, merge, expand, and translate Struql JSON into SQL.
Installs: 4
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 1
Forks: 0
Open Issues: 0
pkg:composer/ddbase3/php-struql
Requires
- php: ^8.1
Requires (Dev)
- phpunit/phpunit: ^10.0
README
Struql is a modular, extensible, and phase-based query processing framework for PHP. It empowers developers to define, normalize, simplify, and compile structured query logic into executable SQL โ all using a clean and extensible handler-based architecture.
๐ Why Struql?
Struql was designed to solve a recurring problem: building highly dynamic and structured queries without tying your code to SQL strings or rigid query builders. With Struql, you can:
- Parse structured query inputs from users or APIs
- Normalize and enrich the query logic
- Automatically resolve joins and field variants
- Generate safe and dialect-specific SQL queries
๐ฆ Features
- Four processing phases: Parse โ Normalize โ Simplify โ Compile
- Handler architecture: Each transformation is modular and isolated
- JOIN auto-resolution: Based on smart field inference
- SQL dialect support: MySQL, MSSQL, PostgreSQL
- Composable processors: Reusable across contexts
- Readable, testable, and extendable code
๐งฑ Architecture Overview
[ Input Query ]
โ
[ Parse Phase ]
โ
[ Normalize Phase ]
โ
[ Simplify Phase ]
โ
[ Compile Phase ]
โ
[ SQL String ]
Each phase is managed by a Processor, which consists of ordered Handlers. A handler is a class that inspects and transforms the query object for a specific purpose.
๐งฉ Key Concepts
โ Processors and Handlers
Each handler must implement:
supportedTypes()โ which input types it processesrun(mixed $input, array &$context): mixedโ transformation logic
๐ง Phase Responsibilities
| Phase | Purpose |
|---|---|
parse |
Parses external input (e.g. query strings) into PHP objects |
normalize |
Expands shorthand field syntax, dollar-fields, top-level filters |
simplify |
Resolves aliases, inferred joins, expands derived objects |
compile |
Transforms the object into executable SQL |
๐งช Example Usage
use Struql\Processor\NormalizePhaseProcessor; use Struql\Processor\CompilePhaseProcessor; use Struql\Handler\DollarFieldToFieldHandler; use Struql\Handler\FieldsToWhereHandler; use Struql\Handler\SqlCompilerHandler; use Struql\Handler\SqlDialect; // Normalization $normalize = new NormalizePhaseProcessor(); $normalize->addHandler(new DollarFieldToFieldHandler()); $normalize->addHandler(new FieldsToWhereHandler()); $query = $normalize->process([ 'type' => 'selectUser', '$user!optional.status' => 'active', 'limit' => 10, 'offset' => 20, 'orderBy' => [ (object)[ 'type' => 'field', 'table' => 'user', 'name' => 'id', 'direction' => 'DESC' ] ] ]); // Compilation $compile = new CompilePhaseProcessor(); $compile->addHandler(new SqlCompilerHandler(SqlDialect::MySQL)); $sql = $compile->process($query); echo $sql;
Output SQL:
SELECT `user`.`id`, `user`.`login`, `user`.`name` FROM `user` LEFT JOIN `profile` ON `user`.`id` = `profile`.`user_id` WHERE `user`.`status` = 'active' ORDER BY `user`.`id` DESC LIMIT 10 OFFSET 20
๐ ๏ธ Built-in Handlers
Normalize Phase
DollarFieldToFieldHandler: Converts$table!variant.fieldtofieldobjects withtable,name, andvariantFieldsToWhereHandler: Converts top-level field-value pairs towhereconditions
Compile Phase
-
SqlCompilerHandler: Converts normalized query objects to SQL strings; supports:- Joins (INNER, LEFT)
- Conditions with
AND,OR,NOT - ORDER BY, GROUP BY, HAVING, LIMIT, OFFSET
- Dialect-specific quoting
๐ Extending Struql
To add a new transformation or compiler step, create a new handler:
class MyCustomHandler extends AbstractHandler { public function supportedTypes(): array { return ['object']; } public function run(mixed $input, array &$context): mixed { // Transform the $input as needed return $input; } }
Register it in your processor:
$normalize->addHandler(new MyCustomHandler());
๐ Use Cases
- Backend APIs that accept dynamic filters from users (e.g. dashboards, analytics)
- Middleware layers that convert API calls to database queries
- CMS systems with dynamic content filtering
- Query conversion pipelines for SQL dialect adaptation
๐ File Structure
src/
Core/
AbstractHandler.php
Processor.php
Handler/
DollarFieldToFieldHandler.php
FieldsToWhereHandler.php
SqlCompilerHandler.php
SqlDialect.php
Processor/
NormalizePhaseProcessor.php
CompilePhaseProcessor.php
๐ Future Plans
- โ Automatic join resolution via used fields
- ๐ฒ Validation layer for input checking before compilation
- ๐ฒ Support for INSERT, UPDATE, DELETE queries
- ๐ฒ Full support for subqueries and expressions
๐ License
This project is open-source and available under the MIT License.
๐ค Contributing
Contributions are welcome! Create a feature branch and submit a pull request. Please include tests where applicable.
๐ง Summary
Struql is a powerful and extensible query transformation engine. Its handler-based architecture allows developers to fully control and customize every aspect of query interpretation and SQL generation โ from API input to final query execution.
Ideal for teams building APIs, dashboards, CMS backends, or data-driven platforms.