Surqlize builds a SELECT as a typed query object. You start it from a model, refine it with chained methods, and either compile it to a SurrealQL string or execute it through the SDK executor.
$query = User::select(fn ($user) => [$user->name, $user->age])
->where(fn ($user) => $user->age->gte(18))
->orderBy(fn ($user) => $user->name->asc());
$sql = $query->compile();
// SELECT name, age FROM user WHERE age >= 18 ORDER BY name ASC
$users = $query->collectModels();The closures receive a typed field set, so field names, conditions, and projections are checked against your model. You can also pass plain strings where you prefer.
Selecting fields
Pass a closure that returns the fields to select, or an array of field names. query() is shorthand for SELECT *.
User::select(fn ($user) => [$user->name, $user->age])->compile();
// SELECT name, age FROM user
User::select(['name', 'age'])->compile();
// SELECT name, age FROM user
User::query()->compile();
// SELECT * FROM userWhere clauses
A where() closure returns one predicate, or a list of predicates that are combined with AND.
User::select(fn ($user) => [$user->name])
->where(fn ($user) => $user->age->gte(18))
->compile();
// SELECT name FROM user WHERE age >= 18
User::select(fn ($user) => [$user->name])
->where(fn ($user) => [
$user->name->eq('beau'),
$user->age->gte(18),
])
->compile();
// SELECT name FROM user WHERE name = "beau" AND age >= 18Field helpers map to SurrealQL operators.
| Helper | Operator |
|---|---|
eq($value) | = |
notEq($value) | != |
gt($value) | > |
gte($value) | >= |
lt($value) | < |
lte($value) | <= |
includes($value) | INCLUDES |
contains($value) | CONTAINS |
like($value) | LIKE |
condition($operator, $value) | A custom operator |
Ordering
orderBy() accepts a field helper, or a field plus a direction.
User::query()->orderBy(fn ($user) => $user->name->asc())->compile();
// SELECT * FROM user ORDER BY name ASC
User::query()->orderBy(fn ($user) => $user->name, 'DESC')->compile();
// SELECT * FROM user ORDER BY name DESCFetching links
fetch() resolves record links so related records are returned inline.
User::select(fn ($user) => [$user->name])
->fetch(fn ($user) => $user->address)
->compile();
// SELECT name FROM user FETCH addressPagination
page() sets a page and page size. limit() and start() give the same control directly.
User::query()->page(page: 3, perPage: 25)->compile();
// SELECT * FROM user LIMIT 25 START 50
User::query()->limit(25)->start(50);Projections and aggregates
Combine projection helpers with groupBy() to aggregate.
use Surqlize\Query\Fields\Projection;
User::select(fn ($user) => [
$user->age,
Projection::count()->as('total'),
])
->groupBy(fn ($user) => $user->age)
->orderBy('total', 'DESC')
->compile();
// SELECT age, count() AS total FROM user GROUP BY age ORDER BY total DESCThe available helpers are Projection::count(), Projection::sum($field), Projection::mean($field), and Projection::raw($expression). Chain ->as('alias') to name the result.
Advanced SELECT clauses
Surqlize supports the wider set of SurrealQL SELECT clauses, compiled in the correct order.
User::select(['*'])
->omit('password')
->withIndex('idx_user_email')
->where(fn ($user) => $user->age->gte(18))
->split('tags')
->orderBy(fn ($user) => $user->name->desc())
->limit(10)
->start(20)
->fetch(fn ($user) => $user->address)
->timeout(5)
->tempFiles()
->explain(full: true)
->compile();
// SELECT * OMIT password FROM user WITH INDEX idx_user_email WHERE age >= 18
// SPLIT tags ORDER BY name DESC LIMIT 10 START 20 FETCH address
// TIMEOUT 5s TEMPFILES EXPLAIN FULLOther clause helpers include withoutIndex(), groupAll(), and withoutFrom(). timeout() takes an amount and an optional unit (s by default).
Selecting values
selectValue() builds a SELECT VALUE query that returns scalar rows.
$name = User::selectValue(fn ($user) => $user->name)
->where(fn ($user) => $user->age->gte(18))
->first();SELECT VALUE rows are scalars and cannot be hydrated with collectModels().
Executing a query
| Method | Result |
|---|---|
compile() | A literal SurrealQL string, for debugging and tests |
toBoundQuery() | An SDK BoundQuery with parameter-bound values |
collect() | A list of raw rows |
collectModels() | A list of hydrated models |
lazyModels() | A generator of hydrated models |
first() | The first scalar or model, depending on the query |
explainPlan() | The raw rows from an EXPLAIN query |
$users = User::query()
->where(fn ($user) => $user->age->gte(18))
->collectModels();
foreach ($users as $user) {
echo $user->name;
} compile() produces a literal string for inspection and deterministic tests. Runtime execution uses toBoundQuery() under the hood, so values are sent as bound parameters rather than interpolated into the query text.
Learn more
Mutations for create, update, and delete
Edges and graph for graph traversal in a select
Search, vector, and geometry for specialised field helpers