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.
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
- 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
[ 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.
Each handler must implement:
supportedTypes()
– which input types it processesrun(mixed $input, array &$context): mixed
– transformation logic
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 |
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
DollarFieldToFieldHandler
: Converts$table!variant.field
tofield
objects withtable
,name
, andvariant
FieldsToWhereHandler
: Converts top-level field-value pairs towhere
conditions
-
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
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());
- 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
src/
Core/
AbstractHandler.php
Processor.php
Handler/
DollarFieldToFieldHandler.php
FieldsToWhereHandler.php
SqlCompilerHandler.php
SqlDialect.php
Processor/
NormalizePhaseProcessor.php
CompilePhaseProcessor.php
- ✅ 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
This project is open-source and available under the MIT License.
Contributions are welcome! Create a feature branch and submit a pull request. Please include tests where applicable.
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.