ObjectQuel is a domain-level query engine with integrated ORM capabilities. It lets you describe data relationships and constraints declaratively, while the engine determines optimal execution across SQL, post-processing, and hybrid data sources.
// 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.
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
Where QUEL's declarative approach delivers the most value
Traverse multiple relationship levels without manual join configuration.
Adopt gradually alongside existing database code - no big-bang rewrite required.
Combine SQL databases and JSON APIs in unified queries.
All queries use parameterized statements automatically - zero SQL injection risk.
The query decomposer analyzes structure and optimizes execution paths automatically.
Native integration with Canvas PHP - zero configuration needed when using both together.
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
$config = new Configuration();
$config->setDsn('mysql://user:pass@localhost/db');
$config->setEntityPath(__DIR__ . '/Entities/');
$entityManager = new EntityManager($config);
// Query immediately
$users = $entityManager->find(User::class, 10);
Open source and MIT licensed
Join developers who've already simplified their database code with ObjectQuel