Nette Documentation Preview

syntax
Transakce
*********

.[perex]
Transakce zaručují, že se buď provedou všechny operace v rámci transakce, nebo se neprovede žádná. Jsou užitečné pro zajištění konzistence dat při složitějších operacích.


Základní použití
================

Nejjednodušší způsob použití transakcí vypadá takto:

```php
$db->beginTransaction();
try {
    $db->query('DELETE FROM articles WHERE id = ?', $id);
    $db->query('INSERT INTO audit_log', [
        'article_id' => $id,
        'action' => 'delete'
    ]);
    $db->commit();
} catch (\Exception $e) {
    $db->rollBack();
    throw $e;
}
```

Mnohem elegantněji můžete to samé zapsat pomocí metody `transaction()`:

```php
$db->transaction(function ($db) use ($id) {
    $db->query('DELETE FROM articles WHERE id = ?', $id);
    $db->query('INSERT INTO audit_log', [
        'article_id' => $id,
        'action' => 'delete'
    ]);
});
```

Metoda `transaction()` může také vracet hodnoty:

```php
$count = $db->transaction(function ($db) {
    $result = $db->query('UPDATE users SET active = ?', true);
    return $result->getRowCount(); // vrátí počet aktualizovaných řádků
});
```


Zanořené transakce .{data-version:4.0}
======================================

Nette Database podporuje zanořování transakcí pomocí SQL savepointů. To znamená, že můžete spustit transakci uvnitř jiné transakce. Zde je jednoduchý příklad:

```php
$db->transaction(function ($db) {
    // hlavní transakce
    $db->query('INSERT INTO users', ['name' => 'John']);

    // vnořená transakce
    $db->transaction(function ($db) {
        $db->query('UPDATE users SET role = ?', 'admin');
        // pokud zde nastane chyba, vrátí se zpět jen vnořená transakce
        // hlavní transakce pokračuje dál
    });

    // pokračování hlavní transakce
    $db->query('INSERT INTO user_log', ['action' => 'user created']);
});
```

.[note]
Podkladový mechanismus využívá ve skutečnosti jen jednu transakci na úrovni databáze a vnořené transakce emuluje pomocí savepointů. Toto chování je stejné pro všechny databáze a je zcela transparentní.


Auto-commit režim .{data-version:4.0}
=====================================

Auto-commit určuje, zda se každý dotaz automaticky provede v samostatné transakci. Ve výchozím nastavení je auto-commit zapnutý, což znamená, že každý dotaz tvoří samostatnou transakci.

Auto-commit můžete vypnout v konfiguraci:

```neon
database:
    dsn: 'mysql:host=127.0.0.1;dbname=test'
    user: root
    password: secret
    options:
        autoCommit: false    # vypne auto-commit
```

nebo v kódu:

```php
$db->setAutoCommit(false);
```

Při vypnutém auto-commitu se automaticky spustí nová transakce v těchto případech:
- při připojení k databázi
- po dokončení předchozí transakce (commit nebo rollback)

.[note]
Pokud změníte nastavení auto-commitu během aktivní transakce, transakce se automaticky potvrdí.

Transakce

Transakce zaručují, že se buď provedou všechny operace v rámci transakce, nebo se neprovede žádná. Jsou užitečné pro zajištění konzistence dat při složitějších operacích.

Základní použití

Nejjednodušší způsob použití transakcí vypadá takto:

$db->beginTransaction();
try {
    $db->query('DELETE FROM articles WHERE id = ?', $id);
    $db->query('INSERT INTO audit_log', [
        'article_id' => $id,
        'action' => 'delete'
    ]);
    $db->commit();
} catch (\Exception $e) {
    $db->rollBack();
    throw $e;
}

Mnohem elegantněji můžete to samé zapsat pomocí metody transaction():

$db->transaction(function ($db) use ($id) {
    $db->query('DELETE FROM articles WHERE id = ?', $id);
    $db->query('INSERT INTO audit_log', [
        'article_id' => $id,
        'action' => 'delete'
    ]);
});

Metoda transaction() může také vracet hodnoty:

$count = $db->transaction(function ($db) {
    $result = $db->query('UPDATE users SET active = ?', true);
    return $result->getRowCount(); // vrátí počet aktualizovaných řádků
});

Zanořené transakce

Nette Database podporuje zanořování transakcí pomocí SQL savepointů. To znamená, že můžete spustit transakci uvnitř jiné transakce. Zde je jednoduchý příklad:

$db->transaction(function ($db) {
    // hlavní transakce
    $db->query('INSERT INTO users', ['name' => 'John']);

    // vnořená transakce
    $db->transaction(function ($db) {
        $db->query('UPDATE users SET role = ?', 'admin');
        // pokud zde nastane chyba, vrátí se zpět jen vnořená transakce
        // hlavní transakce pokračuje dál
    });

    // pokračování hlavní transakce
    $db->query('INSERT INTO user_log', ['action' => 'user created']);
});

Podkladový mechanismus využívá ve skutečnosti jen jednu transakci na úrovni databáze a vnořené transakce emuluje pomocí savepointů. Toto chování je stejné pro všechny databáze a je zcela transparentní.

Auto-commit režim

Auto-commit určuje, zda se každý dotaz automaticky provede v samostatné transakci. Ve výchozím nastavení je auto-commit zapnutý, což znamená, že každý dotaz tvoří samostatnou transakci.

Auto-commit můžete vypnout v konfiguraci:

database:
    dsn: 'mysql:host=127.0.0.1;dbname=test'
    user: root
    password: secret
    options:
        autoCommit: false    # vypne auto-commit

nebo v kódu:

$db->setAutoCommit(false);

Při vypnutém auto-commitu se automaticky spustí nová transakce v těchto případech:

  • při připojení k databázi
  • po dokončení předchozí transakce (commit nebo rollback)

Pokud změníte nastavení auto-commitu během aktivní transakce, transakce se automaticky potvrdí.