Surqlize can manage your database schema. A model links to a schema through the #[Schema] attribute, and the schema describes the DEFINE statements to apply. You can write raw SurrealQL, use the fluent DSL, or mix both.
Schema contracts
A schema implements Surqlize\Model\SchemaContract. definitions() returns the schema statements, and rules() returns PHP validation callbacks that run before persistence operations such as create() and save().
use Surqlize\Model\SchemaContract;
final class UserSchema implements SchemaContract
{
public function definitions(): array
{
return [
'DEFINE TABLE user SCHEMAFULL;',
'DEFINE FIELD name ON user TYPE string;',
'DEFINE FIELD age ON user TYPE int;',
];
}
public function rules(): array
{
return [
'name' => static fn (mixed $value): bool|string =>
is_string($value) && $value !== '' ? true : 'Name is required.',
];
}
}Link the schema to a model with #[Schema].
use Surqlize\Attributes\Schema;
use Surqlize\Attributes\Table;
use Surqlize\Model\Model;
#[Table('user')]
#[Schema(UserSchema::class)]
final class User extends Model
{
// ...
}A validation rule returns true when the value is valid, or an error string when it is not.
The schema DSL
The fluent DSL generates DEFINE statements for tables, fields, analysers, indexes, and assertions, so you describe the schema in PHP rather than strings.
use Surqlize\Schema\Schema;
$schema = Schema::table('article')->schemafull();
$schema->analyzer('english')
->tokenizers(['class'])
->filters(['lowercase']);
$schema->field('title')
->string()
->assert(fn ($value) => $value->required()->minLength(3));
$schema->field('email')
->string()
->assert(fn ($value) => $value->email())
->unique('idx_article_email');
$schema->field('embedding')
->vector(3);
$schema->index('idx_article_embedding')
->fields(['embedding'])
->hnsw(3);
$definitions = $schema->definitions();Field types
field() returns a field definition with type helpers including string(), int(), float(), bool(), datetime(), array(), record(), geometry(), and vector(). Further modifiers include default(), value(), computed(), readonly(), comment(), assert(), and unique().
Assertions
assert() takes a closure that receives an assertion builder. It supports required(), email(), minLength(), maxLength(), between(), greaterThan(), lessThan(), matchesRegex(), isRecord(), and customExpression().
Indexes and analysers
index() builds an index with fields(), and unique(), fullText(), or hnsw() for the index kind. analyzer() builds a search analyser with tokenizers() and filters().
Mixing raw statements and the DSL
A schema contract can return a mix of raw strings and DSL objects.
use Surqlize\Model\SchemaContract;
use Surqlize\Schema\Schema;
final class ArticleSchema implements SchemaContract
{
public function definitions(): array
{
return [
'DEFINE TABLE legacy;',
Schema::table('article')
->schemafull()
->field('title')
->string()
->assert(fn ($value) => $value->minLength(3)),
];
}
public function rules(): array
{
return [];
}
}Applying a schema
Apply the schema for a set of models with the SchemaManager. Pass an executor, or rely on the registered one.
use Surqlize\Model\SchemaManager;
(new SchemaManager())->apply([
User::class,
Address::class,
], $surreal);Use definitions() instead of apply() to inspect the statements without running them. You can also apply schemas from the CLI.
Learn more
Models for the
#[Schema]attributeCode generation and CLI to apply schemas from the command line
DEFINE for the SurrealQL schema statements