Registry
The SQLite index behind find(): query pages by view, published state and content fields, search them, and rebuild when files change outside the CMS.
What it is
The registry is a SQLite index at data/storage/registry.db. It maps every page and user UUID to its path, view, published state, access and timestamps, and indexes content fields for filtering and search, so queries don't scan the page tree.
It is a cache of the files on disk, not a source of truth. It builds itself on first boot, Page::save() and the delete hooks keep it current, and it can always be rebuilt from data/pages/.
Querying
A query is a comma-separated list of conditions, all of which must match:
$app->find('view=article, published=1, sort=-created, limit=4');
The result is a collection of Page objects, loaded lazily as you iterate. The same query string works everywhere:
| Call | Searches |
|---|---|
$app->find($query) |
Pages and users, unless you add type=page |
$page->find($query) |
Pages below $page, at any depth |
$page->children($query) |
Direct children only, hidden pages excluded |
{find($query)} in Latte |
Pages, from the root |
phlat page:list $query |
The same, from the CLI |
Results include only what the current visitor may open: no unpublished pages, no pages behind an access they don't meet, nothing beneath those. Editors and the CLI see everything. See Publishing and access.
Fields
Structural fields come straight from the index: type, root, depth, view, role, published, access, hidden, locked, path, created, updated. Any other name is a content field from data.json:
$app->find('view=article, tag*=php');
Operators
| Operator | Meaning |
|---|---|
= / != |
Equal / not equal |
*= |
Contains |
^= / $= |
Starts with / ends with |
< > <= >= |
Comparison; numeric on content fields |
Separate alternatives with |: view=article|post.
Sorting and paging
$app->find('view=article, sort=-created, limit=10, offset=20');
sort=field is ascending, sort=-field descending.
Full-text search
search= runs a ranked match and sorts by relevance unless you give a sort. fuzzy=true widens each term to nearby indexed words so typos still match; it does nothing without search=.
$app->find('type=page, search=flat file cms');
$app->find('type=page, search=flat file, fuzzy=true');
A field's options can set search.weight (high, normal, low) or search.enabled to change how it ranks or whether it is indexed.
When it drifts
Changes through Page::save(), the admin or the CLI update the registry. Editing files directly doesn't: hand-edited JSON, pages pulled from git, a restored backup. Then run:
phlat registry:check # report drift and bad UUIDs
phlat registry:check --heal # reindex missing and stale pages, drop orphaned rows
phlat registry:rebuild # re-scan everything from disk
phlat registry:rebuild blog # re-scan one page and its descendants
check also reports malformed index.json, missing UUIDs and duplicate UUIDs. Those need a person to decide, so --heal never touches them.
A registry schema change between releases drops and rebuilds the index on the next boot.