# Query builders

Reference for the fluent query builders in version 2 of the PHP SDK, including select, create, update, delete, insert, and relate.

The fluent builders compile a statement and run it through the connection. Each builder method on `Surreal` returns a builder object you configure with chained calls, then run with `execute()` or inspect with `compile()`.

All builders extend `QueryBuilder` in the `SurrealDB\SDK\Query` namespace.

## Shared methods

Every builder provides these methods.

| Method | Returns | Description |
|--------|---------|-------------|
| `execute()` | `mixed` | Run the statement and return the first statement's result |
| `compile()` | [`BoundQuery`](/docs/reference/php/v2/api/utilities.md#boundquery) | Compile to SurrealQL and bindings without running |
| `json(bool $json = true)` | `static` | Request JSON-compatible results |

## Raw queries

### `run()` {#run}

Execute raw SurrealQL with optional bindings. Returns one result per statement.

```php title="Syntax"
$db->run(string $surql, array $bindings = []): array
```

```php
[$people] = $db->run('SELECT * FROM person WHERE age > $min', ['min' => 18]);
```

### `query()` {#query}

Execute a pre-built [`BoundQuery`](/docs/reference/php/v2/api/utilities.md#boundquery). Returns one result per statement.

```php title="Syntax"
$db->query(BoundQuery $query): array
```

## `select()` {#select}

Start a `SELECT`. Accepts a `RecordId`, `Table`, or string target.

```php title="Methods"
->fields(string ...$fields)   // SELECT specific fields
->value(string $field)        // SELECT VALUE for one field
->where(string|BoundQuery $cond)
->start(int $start)
->limit(int $limit)
->fetch(string ...$fields)    // resolve record links
->timeout(string $duration)   // e.g. "5s"
->version(string $datetime)   // historical read
```

```php
$people = $db->select(new Table('person'))
    ->fields('name', 'age')
    ->where('age >= 18')
    ->limit(10)
    ->execute();
```

## `create()` {#create}

Start a `CREATE`. Accepts a `RecordId`, `Table`, or string target.

```php title="Methods"
->content(array|object $data)       // CONTENT
->patch(array $patches)             // PATCH
->output(Output $output)            // RETURN clause
->timeout(string $duration)
->version(string $datetime)
```

```php
$person = $db->create(new RecordId('person', 'tobie'))
    ->content(['name' => 'Tobie'])
    ->execute();
```

## `update()` and `upsert()` {#update}

Start an `UPDATE` or `UPSERT`. `update()` modifies existing records; `upsert()` creates the record if it does not exist.

```php title="Methods"
->content(array|object $data)   // replace the record
->merge(array|object $data)     // merge fields
->replace(array|object $data)   // REPLACE
->patch(array $patches)         // JSON Patch
->where(string|BoundQuery $cond)
->output(Output $output)
->timeout(string $duration)
```

```php
$db->update(new RecordId('person', 'tobie'))
    ->merge(['age' => 33])
    ->execute();

$db->upsert(new RecordId('person', 'tobie'))
    ->content(['name' => 'Tobie', 'age' => 33])
    ->execute();
```

## `delete()` {#delete}

Start a `DELETE`. It defaults to `RETURN BEFORE`, so deleted records are returned.

```php title="Methods"
->output(Output $output)
->timeout(string $duration)
->version(string $datetime)
```

```php
$db->delete(new RecordId('person', 'tobie'))->execute();
```

## `insert()` {#insert}

Start an `INSERT`. Pass a target table and records, or records alone when each carries its own ID.

```php title="Methods"
->relation()   // INSERT RELATION
->ignore()     // INSERT IGNORE
->output(Output $output)
->timeout(string $duration)
->version(string $datetime)
```

```php
$db->insert(new Table('person'), [
    ['name' => 'Alice'],
    ['name' => 'Bob'],
])->execute();
```

## `relate()` {#relate}

Start a `RELATE`, creating one or more graph edges.

```php title="Methods"
->content(array|object $data)   // store data on the edge
->unique()
->output(Output $output)
->timeout(string $duration)
->version(string $datetime)
```

```php
$db->relate(
    new RecordId('person', 'tobie'),
    new Table('likes'),
    new RecordId('post', 'surrealdb'),
)->content(['since' => 2024])->execute();
```

## `call()` {#call}

Invoke a SurrealQL or SurrealML function by name. `run()` already handles raw SurrealQL, so function invocation has its own method.

```php title="Syntax"
$db->call(string $name, ?string $version = null, array $args = []): RunQuery
```

```php
$greeting = $db->call('fn::greet', null, ['Tobie'])->execute();
```

## `auth()` {#auth}

Compile to `SELECT * FROM ONLY $auth`, returning the authenticated record user.

```php
$me = $db->auth()->execute();
```

## Modifiers

### Output

`output()` accepts the `SurrealDB\SDK\Enum\Output` enum: `NONE`, `NULL_`, `DIFF`, `BEFORE`, `AFTER`.

```php
use SurrealDB\SDK\Enum\Output;

$db->update(new RecordId('person', 'tobie'))
    ->merge(['age' => 33])
    ->output(Output::AFTER)
    ->execute();
```

### Where

`where()` accepts a SurrealQL string or a [`BoundQuery`](/docs/reference/php/v2/api/utilities.md#boundquery) fragment. Use a `BoundQuery` to keep dynamic values parameterised.

### Timeout

`timeout()` accepts a SurrealQL duration string such as `5s` or `1m30s`.

## See also

- [Executing queries](/docs/reference/php/v2/concepts/executing-queries.md) for the guide
- [Core classes](/docs/reference/php/v2/api/core.md) for the `Surreal` entry point
- [Utilities](/docs/reference/php/v2/api/utilities.md) for `BoundQuery` and the `Output` enum
