๐ง Builder
The Builder provides a high-level, entity-oriented way to perform queries on your data models. It is built on top of
the lower-level QueryBuilder and integrates deeply with Hector ORM entity management.
๐ Accessing the Builder
You can access the builder using the static Entity::query() method, or instantiate it directly:
use Hector\Orm\Query\Builder;
$builder = MyEntity::query();
// or
$builder = new Builder(MyEntity::class);
The builder internally uses
hectororm/query: see QueryBuilder documentation. You can also useQueryBuilderindependently of the ORM: seehectororm/queryon GitHub or Packagist.
๐ฏ Finding Entities
Find by Primary Key
$entity = MyEntity::find(1);
Returns the entity or null if not found.
Warning: Passing multiple IDs to find() is deprecated. Use findAll() instead for multiple entities.
Find All
Returns a collection of entities matching the given primary key(s):
$collection = MyEntity::findAll(1);
$collection = MyEntity::findAll(1, 2, 3);
Find or Fail
Throws NotFoundException if not found:
use Hector\Orm\Exception\NotFoundException;
try {
$entity = MyEntity::findOrFail(1);
} catch (NotFoundException $e) {
// Handle exception
}
Find or New
Returns existing entity or creates a new one with default values:
$entity = MyEntity::findOrNew(1, ['foo' => 'value']);
๐ Get by Offset (non-PK access)
These methods retrieve entities by their position in the result set (zero-based offset), not by primary key. Useful when you need the Nth result of a query.
Get / Get or Fail / Get or New
// Get first result (offset 0)
$entity = MyEntity::query()->get();
// Get third result (offset 2)
$entity = MyEntity::query()->where('active', true)->get(2);
// Throw NotFoundException if no result at offset
$entity = MyEntity::query()->getOrFail(0);
// Return new entity with default values if no result at offset
$entity = MyEntity::query()->getOrNew(0, ['status' => 'draft']);
๐ Retrieving All Entities
$collection = MyEntity::all();
Also available via the builder:
$collection = MyEntity::query()->all();
๐ Chunking and Yielding
Use chunk() for memory-friendly batch processing:
MyEntity::query()->chunk(100, function (Collection $entities) {
foreach ($entities as $entity) {
// Process each entity
}
});
With lazy mode disabled (eager fetch per chunk):
MyEntity::query()->chunk(100, function (Collection $collection) {
// Each chunk is fetched eagerly from DB
}, lazy: false);
Use yield() to iterate using a lazy generator. Entities are hydrated one by one as you iterate, minimizing memory usage:
foreach (MyEntity::query()->yield() as $entity) {
// Each entity is loaded on-demand
}
Tip: yield() returns a LazyCollection. The underlying query is executed once, but entities are hydrated lazily during iteration.
๐ข Counting
$count = MyEntity::query()->count();
This will ignore any limit() that was previously applied.
๐ฆ Limiting and Offsetting Results
MyEntity::query()->limit(10)->offset(5)->all();
๐ข Ordering Results
MyEntity::query()->orderBy('created_at', 'DESC')->all();
MyEntity::query()->orderBy('name')->all(); // ASC by default
๐งฎ Conditions
You can filter entities using a fluent API similar to the QueryBuilder.
Where / Having
MyEntity::query()->where('column', 'value')->orWhere('column', '<', 10);
Where In / Not In
MyEntity::query()->whereIn('column', ['foo', 'bar']);
MyEntity::query()->whereNotIn('column', ['foo', 'bar']);
Between / Not Between
MyEntity::query()->whereBetween('column', 1, 10);
MyEntity::query()->whereNotBetween('column', 1, 10);
Greater / Less
MyEntity::query()->whereGreaterThan('column', 5);
MyEntity::query()->whereLessThan('column', 100);
Exists / Not Exists
MyEntity::query()->whereExists($subQuery);
MyEntity::query()->whereNotExists($subQuery);
Where Equals (Smart Inference)
MyEntity::query()->whereEquals([
'status' => 'active', // WHERE status = 'active'
'category_id' => [1, 2, 3], // AND category_id IN (1, 2, 3)
]);
Automatically uses = for scalar values and IN for arrays.
๐ Compatibility with QueryBuilder
All filtering, ordering, joining, and limiting operations are passed to the underlying QueryBuilder, which can be used
directly for low-level control.
If you need full SQL flexibility or want to decouple from ORM, refer to the standalone QueryBuilder documentation.