Transacties

Transacties klinken de doorgewinterde databasegebruiker waarschijnlijk zeer bekend in de oren, maar niet iedereen zal weten wat je met dit principe kunt. Simpel gezegd heb je bij transacties in een database de mogelijkheid om een reeks queries uit te voeren zonder dat je eventuele aanpassingen definitief doorvoert. Aan het einde van deze reeks kun je COMMIT gebruiken om de wijzigingen definitief door te voeren of ROLLBACK om alle wijzigingen terug te draaien.

De PDO extensie biedt ons drie methodes voor het werken met transacties: beginTransaction(), commit() en rollBack(). De eerste methode roepen we aan het begin aan, deze zorgt ervoor dat autocommit uitgezet wordt en dat queries pas definitief doorgevoert worden zodra commit() aangeroepen wordt. De rollback() methode kunnen we gebruiken om gemaakte wijzigingen terug te draaien mocht er een fout optreden.

Voorbeeld 22

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php
try
{
    $db = new PDO('mysql:host=localhost;dbname=test','user','password');
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
    $db->beginTransaction();
    
    $db->query("INSERT INTO tabel (naam) VALUES ('Piet')");
    $db->query("INSERT INTO tabel (naam) VALUES ('Jan')");
    $db->query("INSERT INTO tabel (naam) VALUES ('Karel')");
    $db->query("INSERT INTO tabel (naam) VALUES ('Kees')");
    
    $db->commit();
    
}

catch(PDOException $e)
{

    if(isset($db))
    {

        $db->rollBack();
    }

    
    echo '<pre>';
    echo 'Regel: '.$e->getLine().'<br>';
    echo 'Bestand: '.$e->getFile().'<br>';
    echo 'Foutmelding: '.$e->getMessage();
    echo '</pre>';
}

?>

We zien hier inderdaad de drie methodes waar ik het al eerder over had terug. Na beginTransaction() voeren we een viertal INSERT queries uit. Als alles goed gaat voeren we de wijzigingen definitief door met commit(). Mocht er een fout optreden dan vangen we die op in het catch gedeelte van het script en draaien we alle reeds gemaakte wijzigingen terug.

We moeten we even controleren of $db bestaat, aangezien dit gedeelte ook fouten in de verbinding afvangt. Als daar een fout in optreedt zal $db niet bestaan en zal het aanroepen van rollback() niet mogelijk zijn.

Hoewel ik hier nu 4 losse queries gebruikt heb, kunnen we deze natuurlijk ook weer vervangen door een prepared statement. Dat zou een nettere oplossing geven.

Een ander goed voorbeeld om het gebruik van transacties te verduidelijken is een geldtranscatie tussen twee bankrekeningen van respectievelijk persoon A en B. Er zal 500 euro overgemaakt worden van persoon A naar persoon B, maar persoon A mag natuurlijk geen negatief saldo krijgen.

Daarnaast kan het totale saldo uit de tabel nooit groter of kleiner worden, er kan immers geen geld ontstaan of verdwijnen. Dat betekent dat de ene query niet uitgevoerd mag worden zonder dat de ander ook uitgevoerd wordt. Duidelijk iets om een transactie voor te gebruiken.

Voorbeeld 23: Geldtransactie tussen twee bankrekeningen
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<?php
try
{
    $db = new PDO('mysql:host=localhost;dbname=test','user','password');
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
    $queries[] = "UPDATE rekeningen SET saldo = saldo - 500 WHERE klant = 'A'";
    $queries[] = "UPDATE rekeningen SET saldo = saldo + 500 WHERE klant = 'B'";
    $controle = "SELECT saldo FROM rekeningen WHERE klant = 'A'";
    
    $db->beginTransaction();
    
    foreach($queries as $query)
    {

        $affected = $db->exec($query);
        if($affected == 0)
        {

            throw new PDOException('Update query niet geslaagd: '.$query);
        }
    }

    
    $result = $db->query($controle);
    $row = $result->fetchAll();
    
    if($row[0]['saldo'] < 0)
    {

        throw new PDOException('Saldo niet toereikend');
    }

    
    $db->commit();
    
    
    echo '<pre>'.print_r(get_class_methods($db) ,true).'</pre>';
    
}

catch(PDOException $e)
{

    if(isset($db))
    {

        $db->rollBack();
    }

    
    echo '<pre>';
    echo 'Regel: '.$e->getLine().'<br>';
    echo 'Bestand: '.$e->getFile().'<br>';
    echo 'Foutmelding: '.$e->getMessage();
    echo '</pre>';
}

?>

We beginnen met het uitvoeren van de UPDATE queries. Mocht daar een fout in optreden, dan willen we dat natuurlijk weten dus maken we in dat geval een nieuw PDOException object aan.

Daarna voeren we de controle query uit en controleren het resultaat. Als dit kleiner is dan 0 heeft persoon A een negatief saldo. Omdat dit niet toegestaan is, gooien we er weer een foutmelding tegenaan zodat alle wijzigingen teruggedraaid worden.

Op deze manier zorgt onze transactie ervoor dat er dus nooit een query zonder de ander uitgevoerd kan worden en dat alles teruggedraaid wordt als er ergens een negatief saldo ontstaat.

« Lees de omschrijving en reacties

Inhoudsopgave

  1. Inleiding
  2. Gebruik van de PDO extensie
  3. Uitvoeren van queries
  4. Foutafhandeling
  5. Prepared statements
  6. Transacties
  7. Slotwoord en referenties

PHP tutorial opties

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.