# Migration guide

Move a project from version 1 to version 2 of the SurrealDB PHP SDK, with a method-by-method mapping of the breaking changes.

Version 2 is a rewrite of the PHP SDK. The namespace, the query API, the credential types, and the connection options all changed. This guide maps each v1 pattern to its v2 equivalent.

> [!IMPORTANT]
> Version 2 is published as `2.0.0-alpha.1` and requires PHP `8.4` or later. It is an alpha, so review the changes here and test before upgrading a production project. Version 1 remains the stable release.

## What changed

- The namespace moved from `Surreal\` to `SurrealDB\SDK\`.
- Mutations use fluent builders that end in `execute()`, instead of taking data as a second argument.
- Raw SurrealQL runs through `run()`. In v1, `query()` ran SurrealQL; in v2, `query()` takes a pre-built `BoundQuery`.
- Credentials are typed classes such as `RootAuth`, and `signin()` returns a `Tokens` object instead of a string.
- Connection settings are passed as a `ConnectOptions` object, and `use()` takes positional arguments.
- Data type classes moved to `SurrealDB\SDK\Types` and use named constructors such as `RecordId::from()`.
- Import and export moved to `$db->connection()`.

## 1. Install version 2

Update your PHP version to `8.4` or later, then require the alpha release and a PSR-18 HTTP client.

```bash
composer require surrealdb/surrealdb.php:2.0.0-alpha.1
composer require guzzlehttp/guzzle php-http/discovery
```

## 2. Update the namespace

```php
// v1
use Surreal\Surreal;

// v2
use SurrealDB\SDK\Surreal;
```

## 3. Update the connection

In v2, pass connection settings as a `ConnectOptions` object and select the namespace and database with positional arguments.

```php
// v1
$db->connect('ws://127.0.0.1:8000/rpc');
$db->use(['namespace' => 'surrealdb', 'database' => 'docs']);

// v2
use SurrealDB\SDK\Connection\ConnectOptions;

$db->connect('ws://127.0.0.1:8000/rpc', new ConnectOptions(
    namespace: 'surrealdb',
    database: 'docs',
));
```

## 4. Update authentication

Credentials are now typed classes, and `signin()` returns a `Tokens` object.

```php
// v1
$token = $db->signin(['user' => 'root', 'pass' => 'root']);

// v2
use SurrealDB\SDK\Auth\RootAuth;

$tokens = $db->signin(new RootAuth('root', 'root'));
$token = $tokens->access;
```

Record access uses `RecordAccessAuth`, and the `scope` key is now `access`.

```php
// v1
$db->signin([
    'namespace' => 'surrealdb',
    'database' => 'docs',
    'scope' => 'user',
    'email' => 'a@b.com',
    'pass' => 'secret',
]);

// v2
use SurrealDB\SDK\Auth\RecordAccessAuth;

$db->signin(new RecordAccessAuth(
    namespace: 'surrealdb',
    database: 'docs',
    access: 'user',
    variables: ['email' => 'a@b.com', 'pass' => 'secret'],
));
```

## 5. Update queries

Raw SurrealQL moves from `query()` to `run()`. Mutations become fluent builders.

```php
// v1
$people = $db->query('SELECT * FROM person WHERE age > $min', ['min' => 18]);
$person = $db->create('person:tobie', ['name' => 'Tobie']);
$db->merge('person:tobie', ['age' => 33]);

// v2
$people = $db->run('SELECT * FROM person WHERE age > $min', ['min' => 18]);
$person = $db->create(new RecordId('person', 'tobie'))
    ->content(['name' => 'Tobie'])
    ->execute();
$db->update(new RecordId('person', 'tobie'))
    ->merge(['age' => 33])
    ->execute();
```

## 6. Update data types

Data type classes moved to `SurrealDB\SDK\Types` and use named constructors.

```php
// v1
use Surreal\Cbor\Types\Record\RecordId;
$id = RecordId::create('person', 'tobie');

// v2
use SurrealDB\SDK\Types\RecordId;
$id = RecordId::from('person', 'tobie'); // or new RecordId('person', 'tobie')
```

The `RecordId` properties also changed: `->tb` is now `->table`.

## 7. Update import and export

```php
// v1
$db->import($sql, 'root', 'root');
$dump = $db->export('root', 'root');

// v2
$db->connection()->importSql($sql);
$dump = $db->connection()->exportSql();
```

## Method mapping

| v1 | v2 |
|----|----|
| `new \Surreal\Surreal()` | `new \SurrealDB\SDK\Surreal()` |
| `connect($url, ['namespace' => ..., 'database' => ...])` | `connect($url, new ConnectOptions(namespace: ..., database: ...))` |
| `use(['namespace' => $ns, 'database' => $db])` | `use($ns, $db)` |
| `signin([...]): string` | `signin(new RootAuth(...)): Tokens` |
| `query($sql, $vars)` | `run($sql, $vars)` |
| `select($thing)` | `select($thing)->execute()` |
| `create($thing, $data)` | `create($thing)->content($data)->execute()` |
| `update($thing, $data)` | `update($thing)->content($data)->execute()` |
| `merge($thing, $data)` | `update($thing)->merge($data)->execute()` |
| `patch($thing, $patches)` | `update($thing)->patch($patches)->execute()` |
| `insert($table, $data)` | `insert(new Table($table), $data)->execute()` |
| `insertRelation($table, $data)` | `insert(new Table($table), $data)->relation()->execute()` |
| `delete($thing)` | `delete($thing)->execute()` |
| `relate($from, $edge, $to, $data)` | `relate($from, $edge, $to, $data)->execute()` |
| `run('fn::foo', '1.0', $args)` | `call('fn::foo', '1.0', $args)->execute()` |
| `RecordId::create('t', 'id')` | `RecordId::from('t', 'id')` |
| `Table::create('t')` | `new Table('t')` |
| `import($sql, $user, $pass)` | `connection()->importSql($sql)` |
| `export($user, $pass)` | `connection()->exportSql()` |
| `status(): int` | `status(): ConnectionStatus` |

## Removed and changed APIs

- `info()` is not exposed on the v2 `Surreal` class. Use the `auth()` builder, which compiles to `SELECT * FROM ONLY $auth`.
- The SurrealML import and export helpers (`importML()`, `exportML()`) are not part of the v2 public API.
- `query()` no longer runs raw SurrealQL. It executes a `BoundQuery`; use `run()` for raw statements.
- `status()` returns a `ConnectionStatus` enum rather than an HTTP status integer.

## Learn more

- [v2 overview](/docs/reference/php/v2.md) for the new SDK
- [Executing queries](/docs/reference/php/v2/concepts/executing-queries.md) for the builder API
- [Authentication](/docs/reference/php/v2/concepts/authentication.md) for the credential types
