# TreeLock

> Serializes the writers of one physical table through a row of the nested_sets_lock registry, held until the outermost transaction commits or rolls back.

[API reference](/docs/api/index.md) › [Nested sets behavior](/docs/extensions/nested-sets-behavior/reference/index.md) › TreeLock

| final class | `yii2\extensions\nestedsets\TreeLock` |
| --- | --- |
| Source | [`src/TreeLock.php`](https://github.com/yii2-extensions/nested-sets-behavior/blob/main/src/TreeLock.php#L29) |

Serializes the writers of one physical table through a row of the `nested_sets_lock` registry, held until the
outermost transaction commits or rolls back.

Each acquisition runs in a savepoint and updates the registry row keyed by a hash of the driver name and the physical
table identity; the row lock it takes persists after the savepoint is released. Missing keys are registered while
holding the [`BOOTSTRAP`](/docs/extensions/nested-sets-behavior/reference/treelock/index.md#const-BOOTSTRAP) row, so concurrent first writers never race a unique insert.

## Methods

| Method | Description | Defined by |
| --- | --- | --- |
| [`acquire()`](#method-acquire) static | Acquires the writer lock of the owner's physical table for the remainder of the active outermost transaction. | `TreeLock` |
| [`exists()`](#method-exists) static | Returns whether the query matches any row, reading with the same current-read semantics as coordinate reloads. | `TreeLock` |
| [`one()`](#method-one) static | Returns the first matching record, reading current MySQL coordinates even under an older repeatable-read view. | `TreeLock` |
| [`rollBack()`](#method-rollBack) static | Rolls back the failed scope and clears Yii levels when the server aborted the whole transaction. | `TreeLock` |

## Constants

| Constant | Value | Description | Defined by |
| --- | --- | --- | --- |
| <span id="const-BOOTSTRAP"></span>`BOOTSTRAP` | `'_bootstrap'` | Registry key of the row that serializes the registration of missing table keys. | `TreeLock` |
| <span id="const-TABLE_NAME"></span>`TABLE_NAME` | `'nested_sets_lock'` | Name of the lock registry table, created by the lock migration in the schema of each nested set table. | `TreeLock` |

## Method details

### acquire() <span id="method-acquire"></span>

```php
public static function acquire(yii\db\ActiveRecord $owner, int $timeout): void
```

Acquires the writer lock of the owner's physical table for the remainder of the active outermost transaction.

**Parameters**

| Parameter | Type | Description |
| --- | --- | --- |
| `$owner` | [`yii\db\ActiveRecord`](/docs/api/yii/db/activerecord/index.md) | Record whose physical table is locked. |
| `$timeout` | `int` | Maximum wait in seconds for the registry row lock. |

**Throws**

- [`yii\base\InvalidConfigException`](/docs/api/yii/base/invalidconfigexception/index.md): if `$timeout` is outside `1` through `3600`, if no Yii transaction is active on the owner connection, if the table is not a physical base table visible in the catalog, if the lock migration is not applied (missing bootstrap row, or non-InnoDB tables on MySQL), or if the registry row cannot be registered.
- [`yii\base\NotSupportedException`](/docs/api/yii/base/notsupportedexception/index.md): if [`Connection::$enableSavepoint`](/docs/api/yii/db/connection/index.md#property-enableSavepoint) is `false`, if the driver is not supported, or if a SQLite table is outside the `main` database.
- [`Throwable`](https://www.php.net/manual/en/class.throwable.php): if the lock wait times out or another database error occurs; the savepoint is rolled back.

### exists() <span id="method-exists"></span>

```php
public static function exists(yii\db\ActiveQuery<yii2\extensions\nestedsets\T> $query): bool
```

Returns whether the query matches any row, reading with the same current-read semantics as coordinate reloads.

**Parameters**

| Parameter | Type | Description |
| --- | --- | --- |
| `$query` | [`yii\db\ActiveQuery`](/docs/api/yii/db/activequery/index.md)`<yii2\extensions\nestedsets\T>` | Query to test; it is cloned and its ordering is dropped. |

**Returns**

`bool`: Whether any row matches the query.

### one() <span id="method-one"></span>

```php
public static function one(yii\db\ActiveQuery<yii2\extensions\nestedsets\T> $query): yii2\extensions\nestedsets\T|null
```

Returns the first matching record, reading current MySQL coordinates even under an older repeatable-read view.

The query is modified in place: caching is disabled and, on MySQL, the SQL becomes a `FOR UPDATE` locking read.

**Parameters**

| Parameter | Type | Description |
| --- | --- | --- |
| `$query` | [`yii\db\ActiveQuery`](/docs/api/yii/db/activequery/index.md)`<yii2\extensions\nestedsets\T>` | Query that selects the record. |

**Returns**

`yii2\extensions\nestedsets\T|null`: Matching record, or `null` if no row matches.

### rollBack() <span id="method-rollBack"></span>

```php
public static function rollBack(yii\db\Connection $db, yii\db\Transaction $transaction, Throwable $cause): void
```

Rolls back the failed scope and clears Yii levels when the server aborted the whole transaction.

**Parameters**

| Parameter | Type | Description |
| --- | --- | --- |
| `$db` | [`yii\db\Connection`](/docs/api/yii/db/connection/index.md) | Connection that owns the transaction. |
| `$transaction` | [`yii\db\Transaction`](/docs/api/yii/db/transaction/index.md) | Transaction scope to roll back. |
| `$cause` | [`Throwable`](https://www.php.net/manual/en/class.throwable.php) | Failure that triggered the rollback; used to detect SQL Server deadlocks. |

**Throws**

- [`Throwable`](https://www.php.net/manual/en/class.throwable.php): if the rollback fails for a reason other than SQLite having already discarded the transaction.