Storh

Schema

Schemas are optional. A schema does two independent jobs: it validates every write, and it declares which fields get indexes. Collections without a schema accept any array data.

$schema = Schema::collection('posts')
    ->string('slug')->unique()
    ->string('status')->index()
    ->int('publishedAt')->range()
    ->bool('featured')
    ->required(['slug', 'status']);

$posts = new DocStore($root, 'posts', schema: $schema);

The schema's collection name must match the store's collection name; construction throws otherwise. Passing the schema to the constructor also syncs the declared indexes immediately.

Validation rules

  • required fields must be present in the written data. Presence is what is checked: an explicit null satisfies a required field.
  • Typed fields are checked only when present and non-null. A string field rejects an int value; a float field accepts both float and int.
  • mixed fields accept anything and are useful to mark a field as required or indexed without constraining its type.
  • Fields not declared in the schema are unrestricted.

A failed validation throws a StorageException before anything is written.

Field types and flags

Supported types: string, int, float, bool, mixed.

Flags per field: index() (equality index), unique() (uniqueness enforced at write time), range() (ordered index for gt/lt/between/prefix and ordered range queries), and required().

Schema changes

Indexes are synced when the store is constructed. If a schema change alters the declared index set, the index manifest changes and the affected indexes are rebuilt from the existing records; validation rule changes apply to future writes only and never rewrite stored records.

The same Schema object can be reused to map typed columns in a SQL mirror, including for collections whose store does not itself use the schema.

On this page