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

v1.0.3 2025-05-26 21:07 UTC

This package is auto-updated.

Last update: 2025-11-26 22:25:14 UTC


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 processes
  • run(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.field to field objects with table, name, and variant
  • FieldsToWhereHandler: Converts top-level field-value pairs to where conditions

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.