# 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.

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

```php
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]`.

```php
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.

```php
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.

```php
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](/docs/reference/php/libraries/surqlize/connections.md), or rely on the registered one.

```php
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](/docs/reference/php/libraries/surqlize/code-generation-and-cli.md#schema-apply).

## Learn more

- [Models](/docs/reference/php/libraries/surqlize/models.md) for the `#[Schema]` attribute
- [Code generation and CLI](/docs/reference/php/libraries/surqlize/code-generation-and-cli.md) to apply schemas from the command line
- [DEFINE](/docs/reference/query-language/statements/define/overview.md) for the SurrealQL schema statements
