---
title: "Záznamník zámkov — Testing for Laravel | Roundly"
description: "Zviditeľnite lockForUpdate() a hĺbku transakcie na SQLite — cez trait modelu alebo zaznamenávajúcu gramatiku."
url: https://roundly-consulting.com/sk/open-source/navody/testing-for-laravel/zaznamnik-zamkov
language: sk
---

[Všetky balíky](https://roundly-consulting.com/sk/open-source.md)

[Testing for Laravel](https://roundly-consulting.com/sk/open-source/navody/testing-for-laravel.md)

# Záznamník zámkov

SQLite kompiluje lockForUpdate() na prázdny reťazec, takže test nerozozná uzamknuté čítanie od neuzamknutého — a skutočné FOR UPDATE je na SQLite syntaktická chyba. Dva pozorovateľné varianty zapisujú každý zámok aj hĺbku transakcie, v ktorej prebehol, do LockRecorder. Zachytia súbehy, ktoré by na SQLite zostali neviditeľné: upozornenie, ktoré sa nikdy neotvorilo, úroveň eskalácie upozornenú dvakrát, predaný tovar nad stav skladu.

## Variant A — model sa dá rozšíriť

Pridajte trait RecordsLocks do testovacej podtriedy. Vráti LockRecordingBuilder, ktorý zaznamená každé lock(), lockForUpdate() a sharedLock() v momente, keď sa jeho dopyt vykoná — v hĺbke transakcie, v ktorej sa vykoná —, pričom príkaz prebehne nezmenený:

```php
use Illuminate\Support\Facades\DB;
use RoundlyConsulting\Testing\Fixtures\Concerns\RecordsLocks;
use RoundlyConsulting\Testing\Fixtures\LockRecorder;

// Variant A — the model is subclassable:
final class RecordingCoupon extends Coupon { use RecordsLocks; }

it('locks the coupon inside the transaction', function (): void {
    LockRecorder::flush();

    DB::transaction(fn () => RecordingCoupon::query()->lockForUpdate()->get());

    expect(LockRecorder::recorded())->toHaveCount(1)
        ->and(LockRecorder::recorded()[0]['marker'])->toBe('lock-for-update')
        ->and(LockRecorder::recorded()[0]['transactionDepth'])->toBe(1);
});
```

## Variant B — zámok je v kóde, ktorý nemožno vymeniť

Nainštalujte LockRecordingGrammar na SQLite pripojenie. Zámok skompiluje na koncový SQL komentár, ktorý SQLite bez problémov vykoná, a listenForMarkers() cez DB::listen() zaznamená každý označený dopyt:

```php
use Illuminate\Support\Facades\DB;
use RoundlyConsulting\Testing\Fixtures\LockRecorder;
use RoundlyConsulting\Testing\Fixtures\LockRecordingGrammar;

// Variant B — the model is not subclassable, or the lock is buried in an action:
it('locks the shop row', function (): void {
    $connection = DB::connection();
    $connection->setQueryGrammar(new LockRecordingGrammar($connection));

    LockRecorder::flush();
    LockRecorder::listenForMarkers();

    DB::transaction(fn () => Shop::query()->lockForUpdate()->get());

    expect(LockRecorder::recorded()[0]['sql'])->toContain('/* lock-for-update */')
        ->and(LockRecorder::recorded()[0]['transactionDepth'])->toBe(1);
});
```

LockRecordingGrammar funguje len na SQLite: jej konštruktor pri akomkoľvek inom pripojení vyhodí InvalidArgumentException, pretože na Postgrese či MySQL by nahradila gramatiku enginu a potichu zahodila skutočné FOR UPDATE. Vo vetve s reálnou databázou test postavený na gramatike obmedzte na SQLite — ->skip(fn () => DriverMatrix::driver() !== 'sqlite') —, keďže tam skutočný zámok vezme sám engine.

## Prečo záleží na hĺbke transakcie

Zámok, ktorý skončí v savepointe uvoľnenom ešte pred zápisom do účtovnej knihy, je skutočná trieda chýb — práve kvôli nej neprešiel zamýšľaný pomocník na zamykanie. Hĺbka ju zviditeľní; vnorená transakcia zaznamená hĺbku 2:

```php
DB::transaction(function (): void {
    DB::transaction(function (): void {
        RecordingCoupon::query()->lockForUpdate()->get();
    });
});

// The nested transaction is a savepoint — depth 2, not the outer transaction.
expect(LockRecorder::recorded()[0]['transactionDepth'])->toBe(2);
```

## API LockRecorder

| Metóda | Účel |
| --- | --- |
| `LockRecorder::flush()` | Vyprázdni záznam — volajte v setUp() a pred spustením súbehu. |
| `LockRecorder::recorded()` | Zámky od posledného vyprázdnenia v poradí: zoznam položiek marker, sql a transactionDepth. |
| `LockRecorder::listenForMarkers()` | Zapojenie variantu B — DB::listen(), ktorý zaznamená každý označený dopyt. Zavolajte raz, po nainštalovaní gramatiky. |
| `LockRecorder::record($marker, $transactionDepth, $sql = '')` | Ručné zaznamenanie jedného zámku. |

Značky sú lock-for-update, lock-shared a lock-custom (textová klauzula zámku). Variant A zaznamená zámok pri vykonaní dopytu s prázdnym sql: builder vytvorený mimo transakcie a spustený v nej zaznamená vnútornú hĺbku, zamykajúci builder, ktorý sa nikdy nespustí, nezaznamená nič, a viac volaní zámku na jednom dopyte sa zaznamená raz — so zámkom, s ktorým dopyt prebehol. toSql() sa počíta ako vykonanie a builder spustený znova zaznamená zámok opäť, len ak naň medzitým znova zavoláte metódu zámku. Variant B zaznamená celý vykonaný príkaz.

## Prejavte lásku k open source

Tento balík je zadarmo pod licenciou MIT. Ak vám šetrí čas, jednorazový príspevok alebo členstvo na Patreone nám pomôže ho ďalej udržiavať, testovať a dokumentovať.

[Ďalšie spôsoby podpory vrátane kryptomien](https://roundly-consulting.com/sk/podporte-nas.md)

Odoslaním daru súhlasíte s našimi [podmienkami prijímania darov](https://roundly-consulting.com/sk/podmienky-darov.md).

[Podporte našu open-source prácu (otvorí sa v novej karte)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Pridajte sa k nám na Patreone (otvorí sa v novej karte)](https://www.patreon.com/cw/roundly)

## Chcete to zabudovať do svojho produktu?

Naše balíky integrujeme do zákazkových Laravel a AI riešení. Napíšte nám, na čom pracujete, a ozveme sa do 48 hodín.

[Ponuka do 48 hodín](https://roundly-consulting.com/sk/kontakt.md) [Prezrieť všetky balíky](https://roundly-consulting.com/sk/open-source/navody/testing-for-laravel.md)
