Skip to content

Commit 5a5294b

Browse files
committed
(docs): Update README with hook system documentation
1 parent 57b17ca commit 5a5294b

1 file changed

Lines changed: 41 additions & 8 deletions

File tree

README.md

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -435,21 +435,54 @@ $errors = Query::validate($queries, ['name', 'age', 'status']);
435435
[$limit, $offset] = Query::page(3, 10);
436436
```
437437

438-
**Pluggable extensions**customize attribute mapping, identifier wrapping, and inject extra conditions:
438+
**Hooks**extend the builder with reusable, testable hook classes for attribute resolution and condition injection:
439439

440440
```php
441+
use Utopia\Query\Hook\AttributeMapHook;
442+
use Utopia\Query\Hook\TenantFilterHook;
443+
use Utopia\Query\Hook\PermissionFilterHook;
444+
441445
$result = (new Builder())
442446
->from('users')
443-
->setAttributeResolver(fn(string $a) => match($a) {
444-
'$id' => '_uid', '$createdAt' => '_createdAt', default => $a
445-
})
447+
->addHook(new AttributeMapHook([
448+
'$id' => '_uid',
449+
'$createdAt' => '_createdAt',
450+
]))
451+
->addHook(new TenantFilterHook(['tenant_abc']))
446452
->setWrapChar('"') // PostgreSQL
447-
->addConditionProvider(fn(string $table) => [
448-
"_uid IN (SELECT _document FROM {$table}_perms WHERE _type = 'read')",
449-
[],
450-
])
451453
->filter([Query::equal('status', ['active'])])
452454
->build();
455+
456+
// SELECT * FROM "users" WHERE "status" IN (?) AND _tenant IN (?)
457+
// bindings: ['active', 'tenant_abc']
458+
```
459+
460+
Built-in hooks:
461+
462+
- `AttributeMapHook` — maps query attribute names to underlying column names
463+
- `TenantFilterHook` — injects a tenant ID filter (multi-tenancy)
464+
- `PermissionFilterHook` — injects a permission subquery filter
465+
466+
Custom hooks implement `FilterHook` or `AttributeHook`:
467+
468+
```php
469+
use Utopia\Query\Condition;
470+
use Utopia\Query\Hook\FilterHook;
471+
472+
class SoftDeleteHook implements FilterHook
473+
{
474+
public function filter(string $table): Condition
475+
{
476+
return new Condition('deleted_at IS NULL');
477+
}
478+
}
479+
480+
$result = (new Builder())
481+
->from('users')
482+
->addHook(new SoftDeleteHook())
483+
->build();
484+
485+
// SELECT * FROM `users` WHERE deleted_at IS NULL
453486
```
454487

455488
### ClickHouse Builder

0 commit comments

Comments
 (0)