A query language for PHP, one level above SQL. Inspired by QUEL — the relational query language that predated SQL. Declare data ranges, traverse relationships, filter with regex. ObjectQuel compiles to optimized SQL so you never have to write it.
// Declare data ranges
range of p is Product
range of c is Category via p.categories
// Describe what you want
retrieve (p, category_name=c.name)
where p.price < 100
and c.active = true
Compare how different approaches express the same data intent.
$qb = $em->createQueryBuilder();
$qb->select('p', 'c.name as category_name')
->from(Product::class, 'p')
->leftJoin('p.categories', 'c')
->where('p.price < :maxPrice')
->andWhere('c.active = :active')
->setParameter('maxPrice', 100)
->setParameter('active', true);
$results = $qb->getQuery()->getResult();
You explicitly define joins, chain conditions, and control execution details.
$results = $em->executeQuery("
range of p is Product
range of c is Category via p.categories
retrieve (p, category_name=c.name)
where p.price < :maxPrice
and c.active = true
", [
'maxPrice' => 100
]);
You declare data ranges and constraints. ObjectQuel analyzes the query and determines execution.
Relationships are paths: via p.categories expresses traversal, not SQL join mechanics.
ObjectQuel analyzes ranges and constraints, then generates optimized execution steps automatically.
Based on tuple relational calculus — QUEL’s declarative model for expressing relational intent.
Write an ObjectQuel query against a live database and see the generated SQL instantly.
{{currentSql}}
{{json}}
| id | int |
| name | string |
| string |
| id | int |
| street | string |
| houseNumber | string |
| customerId | int (FK) |
Simple methods for everyday use, and a query language when relationships and logic grow complex
// Find by primary key
$user = $em->find(User::class, $id);
// Find by criteria
$posts = $em->findBy(
Post::class,
[
'published' => true,
'authorId' => 5
]
);
Ideal for straightforward lookups and simple filtering
// Complex relationships and filtering
$results = $em->executeQuery("
range of p is Product
range of c is Category via p.categories
retrieve (p, category_name=c.name)
where p.price < :maxPrice
and c.active = true
and p.name = \"widget*\"
sort by p.name asc
", ['maxPrice' => 100.00]);
Designed for complex relationships, multistep filtering, and non-trivial queries
Capabilities that aren't possible in DQL, Eloquent, or standard query builders
Write where p.name = /^widget/i or p.sku = "ABC*XYZ" natively. No whereRaw, no database-specific functions.
search(p.description, "banana +pear -apple") compiles to the correct full-text implementation for your database — no raw SQL required.
Join a SQL table and a JSON file in a single query. The engine handles cross-source matching automatically.
via p.category is all you write. No join conditions, no foreign key configuration in the query itself.
Complex queries are split into optimized subtasks automatically. You describe the data; the engine determines execution.
Works alongside existing database code. Introduce ObjectQuel queries one at a time — no big-bang rewrite required.
After 25 years writing database queries, I got tired of fighting ORMs that force you to think in SQL joins or drown in method chaining. ObjectQuel brings QUEL’s declarative approach to PHP — declare data ranges and constraints, and let the engine determine execution.
— Floris, Quellabs
From query to hydrated entities
ObjectQuel handles optimization automatically, so you focus on describing data, not execution mechanics.
ObjectQuel handles SQL and JSON sources, then hydrates results into objects
Install ObjectQuel via Composer and start querying with objects immediately
# Install via Composer
composer require quellabs/objectquel
use Cake\Database\Connection;
// Configure ObjectQuel
$config = new Configuration();
$config->setEntityPath(__DIR__ . '/Entities/');
$config->setProxyDir(__DIR__ . '/cache/proxies/');
$config->setMetadataCachePath(__DIR__ . '/cache/metadata/');
// Create CakePHP database connection
$connection = new Connection([
'driver' => 'Cake\Database\Driver\Mysql',
'host' => 'localhost',
'username' => 'user',
'password' => 'pass',
'database' => 'db'
]);
// Initialize EntityManager
$entityManager = new EntityManager($config, $connection);
// Query immediately
$user = $entityManager->find(User::class, 10);
Open source and MIT licensed
A family of open-source tools built around the same philosophy.
Join developers who've already simplified their database code with ObjectQuel