{"id":36252692,"url":"https://github.com/quellabs/objectquel","last_synced_at":"2026-06-03T08:00:34.612Z","repository":{"id":260299863,"uuid":"880847955","full_name":"quellabs/objectquel","owner":"quellabs","description":"ObjectQuel is a domain-level query engine with integrated ORM capabilities.","archived":false,"fork":false,"pushed_at":"2026-05-25T11:08:57.000Z","size":2673,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-05-25T13:09:49.415Z","etag":null,"topics":["database","database-abstraction","datamapper","entity-mapping","object-relational-mapping","orm","query-language"],"latest_commit_sha":null,"homepage":"https://www.objectquel.com","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/quellabs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-10-30T13:26:22.000Z","updated_at":"2026-05-25T11:08:58.000Z","dependencies_parsed_at":"2026-03-07T15:01:48.483Z","dependency_job_id":null,"html_url":"https://github.com/quellabs/objectquel","commit_stats":null,"previous_names":["noescom/objectquel","quellabs/objectquel"],"tags_count":112,"template":false,"template_full_name":null,"purl":"pkg:github/quellabs/objectquel","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quellabs%2Fobjectquel","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quellabs%2Fobjectquel/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quellabs%2Fobjectquel/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quellabs%2Fobjectquel/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/quellabs","download_url":"https://codeload.github.com/quellabs/objectquel/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quellabs%2Fobjectquel/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33854119,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-03T02:00:06.370Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["database","database-abstraction","datamapper","entity-mapping","object-relational-mapping","orm","query-language"],"created_at":"2026-01-11T07:02:04.501Z","updated_at":"2026-06-03T08:00:34.599Z","avatar_url":"https://github.com/quellabs.png","language":"PHP","funding_links":["https://github.com/sponsors/quellabs"],"categories":[],"sub_categories":[],"readme":"# ObjectQuel\n\n[![Latest Version](https://img.shields.io/packagist/v/quellabs/objectquel.svg)](https://packagist.org/packages/quellabs/objectquel)\n[![PHPStan](https://img.shields.io/badge/PHPStan-level%209-brightgreen.svg)](https://phpstan.org)\n[![License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](LICENSE)\n\nA domain-level query language and engine for PHP, with a full ORM attached.\nObjectQuel's declarative syntax inspired by [QUEL](https://en.wikipedia.org/wiki/QUEL_query_languages)\nexpresses entity queries above the table level — relationships, patterns,\nfull-text search, and cross-source joins are first-class expressions, not raw SQL escapes.\nSupports MySQL, PostgreSQL, SQLite, and SQL Server.\n\n```php\n$results = $entityManager-\u003eexecuteQuery(\"\n    range of p is App\\\\Entity\\\\Product\n    range of c is App\\\\Entity\\\\Category via p.categories\n    retrieve (p, c.name as categoryName)\n    where p.price \u003c :maxPrice and c.active = true\n    sort by p.name asc\n\", [\n    'maxPrice' =\u003e 50.00\n]);\n```\n\nThe engine resolves entity relationships, decomposes the query into optimized SQL, and hydrates the results. You write\nintent; ObjectQuel handles the mechanics.\n\n## Installation\n\n```bash\ncomposer require quellabs/objectquel\n```\n\n## Quick start\n\n```php\nuse Quellabs\\ObjectQuel\\Configuration;\nuse Quellabs\\ObjectQuel\\EntityManager;\n\n$config = new Configuration();\n$config-\u003esetEntityNamespace('App\\\\Entity');\n$config-\u003esetEntityPath(__DIR__ . '/src/Entity');\n\n$entityManager = new EntityManager($config, $connection);\n\n// Standard lookups\n$product = $entityManager-\u003efind(Product::class, 101);\n$active  = $entityManager-\u003efindBy(Product::class, ['active' =\u003e true]);\n\n// ObjectQuel for anything more complex\n$results = $entityManager-\u003eexecuteQuery(\"\n    range of p is App\\\\Entity\\\\Product\n    retrieve (p) where p.name = /^Tech/i\n    sort by p.createdAt desc\n    window 0 using window_size 10\n\");\n```\n\n## What the query language can do that others can't\n\nMost ORM query languages are SQL with different syntax. ObjectQuel's abstraction layer sits above SQL, which lets it do\nthings that aren't possible in DQL, Eloquent, or raw query builders:\n\n**Pattern matching and regex in where clauses:**\n\n```php\n// Wildcard matching — no LIKE syntax needed\nretrieve (p) where p.sku = \"ABC*XYZ\"\n\n// Regex with flags\nretrieve (p) where p.name = /^tech/i\n```\n\nThe equivalent in Doctrine requires `$qb-\u003eexpr()-\u003elike()` or a raw `REGEXP` call. In Eloquent you'd write\n`whereRaw('name REGEXP ?', [...])`. ObjectQuel treats patterns as first-class query expressions.\n\n**Full-text search with boolean operators and weighting:**\n\n```php\nretrieve (p) where search(p.description, \"banana +pear -apple\")\n```\n\nNo raw SQL, no engine-specific syntax. The query engine translates this to the appropriate full-text implementation for\nyour database.\n\n**Hybrid data sources — database + JSON in one query:**\n\n```php\nrange of order is App\\\\Entity\\\\OrderEntity\nrange of product is json_source('external/product_catalog.json')\nretrieve (order, product.name, product.manufacturer)\nwhere order.productSku = product.sku and order.status = :status\nsort by order.orderDate desc\n```\n\nObjectQuel can join database entities with JSON files in a single query, applying\ninner, left, or cross joins based on context — the engine handles the cross-source matching.\nNeither Doctrine nor Eloquent can do this. You'd query the database, load the JSON separately, and merge results in PHP.\nObjectQuel also supports JSONPath prefiltering to extract nested structures before the query runs, keeping memory usage\nlow on large files.\n\n**Existence checks as expressions:**\n\n```php\n// In the retrieve clause\nretrieve (p.name, hasOrders=ANY(o.orderId))\n\n// In the where clause\nretrieve (p) where ANY(o.orderId)\n```\n\n**Automatic query decomposition:**\n\nComplex queries are split into optimized sub-tasks by the engine rather than sent as a single monolithic SQL statement.\nThis means ObjectQuel can optimize execution paths that a single SQL query cannot express efficiently.\n\n**Database dialect abstraction:**\n\nFeatures like full-text search, regex matching, and window functions compile to the correct SQL for your target\ndatabase. The same ObjectQuel query runs on MySQL, PostgreSQL, SQLite, and SQL Server without modification. Switching\ndatabases means changing the connection, not rewriting queries.\n\n## Comparison\n\nA multi-entity query with filtering and relationship traversal:\n\n**ObjectQuel:**\n\n```php\n$results = $entityManager-\u003eexecuteQuery(\"\n    range of o is App\\\\Entity\\\\Order\n    range of c is App\\\\Entity\\\\Customer via o.customerId\n    retrieve (o, c.name) where o.createdAt \u003e :since\n    sort by o.createdAt desc\n    window 0 using window_size 20\n\");\n```\n\n**Doctrine DQL:**\n\n```php\n$results = $entityManager-\u003ecreateQuery(\n    'SELECT o, c.name FROM App\\\\Entity\\\\Order o\n     JOIN o.customer c\n     WHERE o.createdAt \u003e :since\n     ORDER BY o.createdAt DESC'\n)-\u003esetParameter('since', $since)\n -\u003esetMaxResults(20)\n -\u003egetResult();\n```\n\n**Eloquent:**\n\n```php\n$results = Order::with('customer:id,name')\n    -\u003ewhere('created_at', '\u003e', $since)\n    -\u003eorderByDesc('created_at')\n    -\u003etake(20)\n    -\u003eget();\n```\n\nThe difference becomes more pronounced with regex filtering, existence checks, hybrid sources, and multi-relationship\ntraversals — operations that require raw SQL or post-processing in other ORMs.\n\n## ORM capabilities\n\nObjectQuel is a full Data Mapper ORM, not just a query language:\n\n- **Entity mapping** — annotation-based with `@Orm\\Table`, `@Orm\\Column`, and relationship annotations\n- **Relationships** — OneToOne, ManyToOne, OneToMany, ManyToMany (via bridge entities)\n- **Unit of Work** — change tracking with persist and flush\n- **Lazy loading** — configurable proxy generation with caching\n- **Immutable entities** — for database views and read-only tables\n- **Optimistic locking** — version-based concurrency control\n- **Cascading** — configurable cascade operations across relationships\n- **Lifecycle events** — pre/post persist, update, and delete via SignalHub\n- **Custom repositories** — optional repository pattern with type-safe access\n- **Indexing** — annotation-driven index management\n- **Migrations** — database schema migrations powered by Phinx\n\n## CLI tooling\n\nObjectQuel ships with Sculpt, a CLI tool for entity and schema management:\n\n```bash\n# Generate a new entity interactively\nphp bin/sculpt make:entity\n\n# Reverse-engineer entities from an existing database table\nphp bin/sculpt make:entity-from-table\n\n# Generate migrations from entity changes\nphp bin/sculpt make:migrations\n\n# Run pending migrations\nphp bin/sculpt quel:migrate\n```\n\n`make:entity-from-table` is particularly useful when adopting ObjectQuel in an existing project — point it at your\ntables and get annotated entities without writing them by hand.\n\n## Framework integration\n\nObjectQuel works standalone or with the [Canvas framework](https://canvasphp.com). The `quellabs/canvas-objectquel`\npackage provides automatic service discovery, dependency injection, and Sculpt CLI integration within Canvas.\n\nFor other frameworks, configure the `EntityManager` directly — it has no framework dependencies.\n\n## Documentation\n\nFull query language reference, entity mapping guide, and architecture docs: **[objectquel.com/docs](https://objectquel.com/docs)**\n\n## Support\n\nIf ObjectQuel saves you time, consider [sponsoring development](https://github.com/sponsors/quellabs).\n\n## License\n\nMIT","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquellabs%2Fobjectquel","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fquellabs%2Fobjectquel","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquellabs%2Fobjectquel/lists"}