• Start

Languages

/

PHP

/

Libraries

/

Surqlize (ORM)

Schema

Define SurrealDB tables, fields, indexes, and analysers in Surqlize with a schema contract or the fluent schema DSL, then apply them with the schema manager.

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.

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 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() 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().

assert() takes a closure that receives an assertion builder. It supports required(), email(), minLength(), maxLength(), between(), greaterThan(), lessThan(), matchesRegex(), isRecord(), and customExpression().

index() builds an index with fields(), and unique(), fullText(), or hnsw() for the index kind. analyzer() builds a search analyser with tokenizers() and filters().

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 [];
}
}

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.

Was this page helpful?