PHP PDO - setAttribute si beginTransaction

Cand se creaza un obiect PDO cu o conexiune la o baza de date, daca apare vreo eroare in transmiterea de comenzi la baza de date determina lansarea PDOException. Daca eroarea nu e preluata cu try ... catch() PHP va opri executia scriptului.
PDOException este o extensie a clasei PHP Exception, prin care pot fi "prinse" erorile.
Cu formula try ... catch(), pe langa faptul ca eroarea e preluata iar scriptul isi continua executia, se poate de asemenea si personaliza mesajul ce va fi afisat. Sintaxa generala este:

- Variabila $e reprezinta obiectul in care e stocata eroare detectata de PHP.
- Metoda getCode() returneaza codul erorii, iar getMessage() mesajul acelei erori. Daca acestea nu sunt adaugate, apare doar mesajul personalizat.

1. setAttribute

Cu metoda PDO setAttribute() se pot seta diferite atribute la obiectul PDO prin care se face conexiunea la baza de date, printre care si modul de raportare a erorilor retinute cu "try ... catch()".
Formula generala de aplicare a acestei metode este:
                $obiectPDO->setAttribute(ATRIBUT, OPTIUNE)
- ATTRIBUT reprezinta tipul atributului care va fi aplicat, iar OPTIUNE este optiunea lui, cum ar fi:


• Iata cum se aplica si ce rezultate da metoda setAttribute(), va fi utilizat acelasi tabel MySQL din lectiile precedente (denumit "sites").

- In urmatorul exemplu se foloseste atributul PDO::ATTR_CASE cu optiunea PDO::CASE_UPPER.
<?php
// Datele de conectare (adresa_server, baza_de_date, nume si parola)
$hostdb = 'localhost';
$namedb = 'teste';
$userdb = 'username';
$passdb = 'password';

try {
  // Conectare si creare obiect PDO
  $dbh = new PDO("mysql:host=$hostdb; dbname=$namedb", $userdb, $passdb);
  $dbh->exec("SET CHARACTER SET utf8");      // Setare encoding caractere UTF-8

  // Seteaza ca numele coloanelor sa fie returnat cu majuscule
  $dbh->setAttribute(PDO::ATTR_CASE, PDO::CASE_UPPER);

  // Selecteaza primul rand
  $sql = "SELECT * FROM `sites` LIMIT 1";
  $datas = $dbh->query($sql)->fetch(PDO::FETCH_ASSOC);      // Executa interogarea si preia in modul FETCH_ASSOC

  // Daca select-ul e facut cu succes ($datas nu e false)
  if($datas !== false) {
    // Se parcurg datele si afiseaza numele coloanelor
    foreach($datas as $col=>$row) {
      echo ' - '. $col;
    }
  }

  $dbh = null;        // Deconectare
}
catch(PDOException $e) {
  echo $e->getMessage();
}
- Script-ul va afisa in browser numele coloanelor, cu majuscule:
- ID - NUME - CATEGORIE - ADRESA

- In exemplu urmator se foloseste metoda setAttribute() pentru a afisa in caz de eroare modul standard returnat de PHP. Se aplica atributul PDO::ATTR_ERRMODE cu optiunea PDO::ERRMODE_WARNING. Pentru a forta generarea erorii, se face un SELECT la o coloana ce nu exista in tabelul "sites".
<?php
// Datele de conectare (adresa_server, baza_de_date, nume si parola)
$hostdb = 'localhost';
$namedb = 'teste';
$userdb = 'username';
$passdb = 'password';

try {
  // Conectare si creare obiect PDO
  $dbh = new PDO("mysql:host=$hostdb; dbname=$namedb", $userdb, $passdb);

  // Seteaza ca mod pt. erori cel standard PHP
  $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
  $dbh->exec("SET CHARACTER SET utf8");      // Setare encoding caractere UTF-8

  // Selecteaza primul rand
  $sql = "SELECT `zzz` FROM `sites` LIMIT 1";
  $datas = $dbh->query($sql);               // Executa interogarea

  // Se parcurg datele si afiseaza ce e in coloana 'zzz'
  foreach($datas as $row) {
    echo $row['zzz'];
  }

  $dbh = null;        // Deconectare
}
catch(PDOException $e) {
  echo $e->getMessage();
}
- Deoarece coloana "zzz" nu exista, va emite urmatoarea eroare:
Warning: PDO::query() [pdo.query]: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'zzz' in 'field list' in E:\server\www\test.php on line 19
Warning: Invalid argument supplied for foreach() in E:\server\www\test.php on line 22
- Daca la setAttribute, in loc de ERRMODE_WARNING se adauga ERRMODE_EXCEPTION, informatia afisata despre eroare va fi:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'zzz' in 'field list'

2. beginTransaction

Metoda beginTransaction() se foloseste impreuna cu commit().
beginTransaction() opreste executia oricarei interogari la baza de date, pana cand e apelata metoda commit(), in acel moment vor fi executate declaratiile SQL adaugate intre aceste 2 metode.
Avantajul acestei tehnici consta in faptul ca pot fi scrise mai multe seturi de interogari SQL, care "stau in asteptare", iar cand e apelata metoda commit() sunt executate toate deodata.


In exemplu urmator se aplica beginTransaction() care permite scrierea de instructiuni SQL fara ca acestea sa fie transmise la serverul MySQL. Se adauga 3 comenzi: prima modifica datele din randul unde id=3 (cu UPDATE), a doua (cu INSERT) adauga un nou rand, iar a treia comanda efectueaza un SELECT, dar in functie de ultimul "id" creat prin INSERT-ul precedent. Toate aceste instructiuni sunt executate cand e apelata metoda commit() (vedeti si explicatiile din cod).
<?php
// Datele de conectare (adresa_server, baza_de_date, nume si parola)
$hostdb = 'localhost';
$namedb = 'teste';
$userdb = 'username';
$passdb = 'password';

try {
  // Conectare si creare obiect PDO
  $dbh = new PDO("mysql:host=$hostdb; dbname=$namedb", $userdb, $passdb);

  $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);       // Seteaza mod exception pt. erori
  $dbh->exec("SET CHARACTER SET utf8");      // Setare encoding caractere UTF-8

  $dbh->beginTransaction();        // Incepe inscrierea comenzilor

  // 1. Modificare date din coloanele "nume" si "adresa", unde id=3
  $dbh->exec("UPDATE `sites` SET `nume`='Cursuri Spaniola', `adresa`='www.marplo.net/spaniola' WHERE `id`=3");
  // 2. Adaugare date in rand nou
  $dbh->exec("INSERT INTO `sites` (`nume`, `categorie`, `adresa`) VALUES ('JavaScript', 'programare', 'www.marplo.net/javascript')");
  $last_id = $dbh->lastInsertId();            // Retine ultimul id adaugat
  // 3. Selectare date din randurile anterioare celui adaugat inainte ("id" mai mic decat $last_id)
  $datas = $dbh->query("SELECT `nume`, `adresa` FROM `sites` WHERE `id`<'$last_id'");

  $dbh->commit();        // Determina transmiterea tuturor comenzilor la MySQL


  // Daca select-ul e facut cu succes ($datas nu e false)
  if($datas !== false) {
    echo 'Ultimul id adaugat: '. $last_id. '<br />';        // Afiseaza ultimul id adaugat (la comanda 2)

    // Se parcurg si afiseaza datele selectate
    foreach($datas as $row) {
      echo $row['nume']. ' - '. $row['adresa']. '<br />';
    }
  }
  
  $dbh = null;        // Deconectare
}
catch(PDOException $e) {
  echo $e->getMessage();
}
?>
- Dupa cum arata si exemplu, aceasta metoda este utila in cazul cand trebuie efectuate mai multe interogari diferite la baza de date, in acelasi script. In plus, imbunatateste si viteza de executie a scriptului, face mai eficient lucru cu multiple interogari la baza de date. Intre comenzile SQL care "sunt in asteptare" se pot adauga diferite instructiuni PHP care sa influenteze urmatoarele comenzi (precum aici SELECT-ul a fost facut in functie de ultimul "id" creat prin comanda precedenta).
- Dupa executie, scriptul afiseaza in browser urmatorul rezultat:
Ultimul id adaugat: 4
Cursuri - Tutoriale - www.marplo.net
Curs PHP-MySQL - www.marplo.net/php-mysql
Cursuri Spaniola - www.marplo.net/spaniola

Daca atributul setAttribute() e setat pe modul ERRMODE_WARNING si apare vreo eroare la una din declaratiile SQL dintre beginTransaction() si commit(), cand acestea sunt transmise la server, celelalte comenzi dupa cea care a determinat eroarea nu mai sunt executate.
Dar daca nu e specificat modul de eroare ERRMODE_WARNING, scriptul continua executia si la celelalte comenzi.

PHP PDO - prepare ... <<-- Anterior ----------- Urmator -->> PHP Functii Anonime - ...

Un Test simplu in fiecare zi

HTML
CSS
JavaScript
PHP-MySQL
Engleza
Spaniola
Care tag adauga rand nou in paragraf?
<b> <br> <p>
Prima linie ...<br>
Alta linie...
Ce proprietate CSS seteaza spatiu dintre litere?
text-size word-spacing letter-spacing
#id {
  letter-spacing: 2px;
}
Ce functie obtine accesul la un element HTML cu un anumit ID?
getElementById() getElementsByTagName() createElement()
var elm = document.getElementById("theID");
var content = elm.innerHTML;
alert(content);
Clic pe instructiunea "echo" utilizata corect.
echo "CoursesWeb.net" echo "CoursesWeb.net"; echo ""CoursesWeb.net";
echo "Adresa URL: http://CoursesWeb.net";
Care din urmatoarele expresii cu "paint" (a picta) se foloseste pentru forma Negativa?
will paint not paint have painted
She does not paint that landscape.
- Ea nu picteaza acel peisaj.
Care din urmatoarele expresii cu "cantar" (a canta) se foloseste pentru propozitie Negativa?
ir a cantar cantaba no cantar
Ella no canta esa canciĆ³n.
- Ea nu canta acel cantec.
PHP PDO - setAttribute si beginTransaction - Tutorial PHP