Usare le transactions in Laravel

Mattepuffo's logo
Usare le transactions in Laravel

Usare le transactions in Laravel

Le transactions praticamente fanno una rollback di tutte le operazioni su database se una non viene eseguita.

Supponiamo uno scenario del genere, in cui eseguiamo diverse operazioni su db a cascata:

  • operazione 1 -> eseguita
  • operazione 2 -> eseguita
  • operazione 3 -> ko

Se usiamo le transactions, le prime due operazioni vengono annullate; in questo modo non rischiamo una inconsistenza nei dati.

Oggi vediamo come usarle in PHP e Laravel.

Abbiamo due modi; il primo più semplice usando la funzione transaction apposita (considerate che l'esempio è ripreso da un caso reale):

class OrfoController extends Controller {

    public function add(Request $req) {
        $data = $req->json()->all();

        if (!empty($data)) {

            try {

                DB::transaction(function () use ($data) {

                    // TESTATE = add_orfo
                    $forn = $data['testata']['co_fornitore'];
                    $bolla = trim($data['testata']['co_bolla']);
                    $dd = date_format(date_create($data['testata']['co_data']), 'Y-m-d H:i:s');
                    $note = trim($data['testata']['co_note']);
                    $dd2 = date_format(date_create($data['testata']['co_data']), 'Ymd');

                    DB::insert('CALL add_orfo(?,?,?,?,?)', array($forn, $bolla, $note, $dd, $dd2));

                    // RIGHE = add
                    $righe = $data['righe'];
                    foreach ($righe as $rr) {
                        $caDescr = trim($rr['co_descrizione']);
                        $caDizionario = $rr['co_dizionario'];
                        $caReparto = $rr['co_reparto'];
                        $caBolla = $bolla;
                        $caUtente = '';
                        $caQta = $rr['co_qta'];
                        $caStato = '';
                        $caPrezzo = 0;
                        $caPrezzoAcq = $rr['co_prezzo'];
                        $caOrd = 0;
                        $caStag = '';

                        $res = DB::select('CALL add_articolo_gest(?,?,?,?,?,?,?,?,?,?)', array(
                            0, $caDescr, $forn, $caReparto, $caDizionario, $caPrezzo, $caPrezzoAcq, 21, 0, $caStag
                        ));

                        var_dump($res);
                    }
                });

            } catch (QueryException $ex) {
                return response()->json([
                    'res' => 'ko',
                    'message' => 'Errore: ' . $ex->getMessage()
                ]);
            }

        } else {
            return response()->json(array(
                "res" => "ko",
                "message" => "Dati mancanti!"
            ));
        }

    }

}

Ci penserà la funzione a fare la commit e l'eventuale rollback.

Se vogliamo avere un maggior controllo, possiamo fare in quest'altro modo:

class OrfoController extends Controller {

    public function add(Request $req) {
        $data = $req->json()->all();

        if (!empty($data)) {

            DB::beginTransaction();

            try {

                // TESTATE = add_orfo
                $forn = $data['testata']['co_fornitore'];
                $bolla = trim($data['testata']['co_bolla']);
                $dd = date_format(date_create($data['testata']['co_data']), 'Y-m-d H:i:s');
                $note = trim($data['testata']['co_note']);
                $dd2 = date_format(date_create($data['testata']['co_data']), 'Ymd');

                DB::insert('CALL add_orfo(?,?,?,?,?)', array($forn, $bolla, $note, $dd, $dd2));

                // RIGHE = add
                $righe = $data['righe'];
                foreach ($righe as $rr) {
                    $caDescr = trim($rr['co_descrizione']);
                    $caDizionario = $rr['co_dizionario'];
                    $caReparto = $rr['co_reparto'];
                    $caBolla = $bolla;
                    $caUtente = '';
                    $caQta = $rr['co_qta'];
                    $caStato = '';
                    $caPrezzo = 0;
                    $caPrezzoAcq = $rr['co_prezzo'];
                    $caOrd = 0;
                    $caStag = '';

                    $res = DB::select('CALL add_articolo_gest(?,?,?,?,?,?,?,?,?,?)', array(
                        0, $caDescr, $forn, $caReparto, $caDizionario, $caPrezzo, $caPrezzoAcq, 21, 0, $caStag
                    ));

                    var_dump($res);
                }

                DB::commit();

            } catch (QueryException $ex) {
                DB::rollback();

                return response()->json([
                    'res' => 'ko',
                    'message' => 'Errore: ' . $ex->getMessage()
                ]);
            }

        } else {
            return response()->json(array(
                "res" => "ko",
                "message" => "Dati mancanti!"
            ));
        }

    }

}

Qui:

  • avviamo la transaction con beginTransaction
  • se le operazioni vanno tutte a buon fine facciamo la commit
  • se viene lanciata l'eccezione, facciamo la rollback

Dovete anche tener presente la configurazione del db però; ad esempio tutto ciò non funziona se le tabelle sono MyISAM; funziona tutto se sono InnoDB.

Enjoy!


Condividi

Commentami!