DAO (Obiecte accesare date) pune la dispozitie un API generic pentru accesul datelor stocate in diverse DBMS (Sisteme de Management Baze de Date). Ca urmare, DBMS-ul poate fi schimbat oricand cu altul, fara sa fie nevoie sa schimbam codul nostru in care folosim DAO sa accesam datele.
Yii DAO este construit pe baza PDO (obiecte date PHP)
care este o extensie PHP ce pune la dispozitie accesul unificat la date stocate
in diverse DBMS cunoscute, precum MySQL si PostgreSQL. De aceea, pentru a folosi
Yii DAO, trebuie instalate extensia PDO si driverul PDO de baze de date specific
(ex. PDO_MYSQL
).
Yii DAO este format in principal din urmatoarele patru clase:
In cele ce urmeaza, explicam folosirea Yii DAO in diverse scenarii.
Pentru a stabili o conexiune, cream o instanta CDbConnection si o activam. Avem nevoie de un DSN (nume pentru sursa de date) pentru a specifica informatiile necesare pentru conectarea la baza de date. Pot fi necesare si un nume si o parola pentru stabilirea conexiunii. Va fi generata o exceptie in cazul in care apare o eroare la stabilirea conexiunii (ex. DSN gresit sau nume/parola gresite).
$connection=new CDbConnection($dsn,$username,$password);
// stabilirea conexiunii. Putem incerca try-catch pentru a identifica exceptii posibile
$connection->active=true;
......
$connection->active=false; // inchidere conexiune
Formatul DSN-ului depinde de driverul PDO folosit. In general,
DSN este format din numele driver-ului PDO, urmat de semnul :
, urmat de sintaxa
conexiunii specifice driver-ului. Pentru informatii complete, trebuie vazuta
documentatia PDO.
Mai jos este o lista de format-uri obisnuite pentru DSN:
sqlite:/path/to/dbfile
mysql:host=localhost;dbname=testdb
pgsql:host=localhost;port=5432;dbname=testdb
Pentru ca CDbConnection este derivata din clasa CApplicationComponent, o putem
folosi de asemenea pe postul de componenta aplicatie.
Pentru a face acest lucru, configuram componenta aplicatie
db
(sau alta componenta aplicatie, daca se doreste)
din configurarea aplicatiei dupa cum urmeaza:
array(
......
'components'=>array(
......
'db'=>array(
'class'=>'CDbConnection',
'connectionString'=>'mysql:host=localhost;dbname=testdb',
'username'=>'root',
'password'=>'password',
),
),
)
Putem dupa aceea sa accesam conexiunea DB prin Yii::app()->db
, care este
activata automat (putem interzice acest comportament prin setarea cu false a
proprietatii CDbConnection::autoConnect. Folosind aceasta metoda
conexiunea DB poate fi utilizata oriunde in cod.
O data ce este stabilita o conexiune DB, instructiunile SQL pot fi executate folosind CDbCommand. Cream o instanta CDbCommand prin apelarea CDbConnection::createCommand() cu instructiunea SQL specificata:
$command=$connection->createCommand($sql);
// daca este necesar, instructiunea SQL poate fi actualizata asa:
// $command->text=$newSQL;
O instructiune SQL este executata prin CDbCommand in unul din urmatoarele doua moduri:
execute(): executa o instructiune SQL,
precum INSERT
, UPDATE
si DELETE
. Daca are succes, returneaza
numarul de randuri afectate.
query(): executa o instructiune SQL care returneaza
randuri de date, precum SELECT
. Daca are succes, returneaza o instanta CDbDataReader
pe care putem sa o parcurgem pentru a folosi randurile de date rezultate.
Pentru usurinta, este implementat de asemenea un set de metode queryXXX()
care returneaza direct rezultatele cererii.
Va fi generata o exceptie daca apare vreo eroare in timpul executiei instructiunilor SQL.
$rowCount=$command->execute(); // executa SQL
$dataReader=$command->query(); // executa o cerere SQL
$rows=$command->queryAll(); // o cerere care returneaza toate randurile rezultate
$row=$command->queryRow(); // o cerere care returneaza primul rand dintre rezultate
$column=$command->queryColumn(); // o cerere care returneaza prima coloana din rezultate
$value=$command->queryScalar(); // o cerere care returneaza primul camp din primul rand
Dupa ce CDbCommand::query() genereaza instanta CDbDataReader, putem extrage
randurile cu datele rezultate prin apelarea repetata a CDbDataReader::read().
Putem de asemenea folosi CDbDataReader intr-un foreach
pentru a extrage fiecare rand in parte.
$dataReader=$command->query();
// apelam repetat read() pana cand returneaza false
while(($row=$dataReader->read())!==false) { ... }
// folosim foreach pentru a trece prin fiecare rand de date
foreach($dataReader as $row) { ... }
// extragem toate randurile o data intr-un singur array
$rows=$dataReader->readAll();
Nota: Spre deosebire de query(), toate metodele
queryXXX()
returneaza date direct. De exemplu, queryRow() returneaza un array care reprezinta primul rand din rezultatele cererii.
Cand o aplicatie executa cateva cereri, operatii de citire sau/si scriere in baza de date, este important sa ne asiguram ca baza de date sa contina toate schimbarile facute de aceste operatii. In aceste cazuri, poate fi initiata o tranzactie, reprezentata prin instanta CDbTransaction din Yii:
Fluxul de lucru de mai sus poate fi implementat folosind urmatorul cod:
$transaction=$connection->beginTransaction();
try
{
$connection->createCommand($sql1)->execute();
$connection->createCommand($sql2)->execute();
//.... alte executii SQL
$transaction->commit();
}
catch(Exception $e) // daca o cerere esueaza, este generata o exceptie
{
$transaction->rollBack();
}
Pentru a evita [atacurile SQL injection] (http://en.wikipedia.org/wiki/SQL_injection) si pentru a imbunatati performanta executiilor cererilor SQL folosite des, putem "prepara" o instructiune SQL cu placeholder-e de parametri optionali care vor fi inlocuiti cu parametrii reali in timpul procesului de conectare de parametri.
Placeholder-ele de parametri pot avea nume (token-uri unice) sau pot fi anonime (prin semne de intrebare). Apelam CDbCommand::bindParam() sau CDbCommand::bindValue() pentru a inlocui aceste placeholder-e cu parametrii reali. Conectarea parametrilor trebuie facuta inainte ca instructiunea SQL sa fie executata.
// o cerere SQL cu 2 placeholdere ":username" si ":email"
$sql="INSERT INTO users(username, email) VALUES(:username,:email)";
$command=$connection->createCommand($sql);
// inlocuim placeholder-ul ":username" cu valoarea reala username
$command->bindParam(":username",$username,PDO::PARAM_STR);
// inlocuim placeholder-ul ":email" cu valoarea reala email
$command->bindParam(":email",$email,PDO::PARAM_STR);
$command->execute();
// inseram un alt rand cu un nou set de parametri
$command->bindParam(":username",$username2,PDO::PARAM_STR);
$command->bindParam(":email",$email2,PDO::PARAM_STR);
$command->execute();
Metodele bindParam() si bindValue() sunt foarte asemanatoare. Singura diferenta este ca bindParam() conecteaza un parametru cu o referinta a unei variabile PHP, in timp ce bindValue() conecteaza un parametru cu o valoare. Pentru parametri care reprezinta blocuri mai de date memorate, este de preferat sa folosim bindParam() din considerente de perfomanta.
Pentru mai multe detalii despre conectarea de parametrii, trebuie vazuta sectiunea din documentatia PHP.
Cand extragem rezultatele cererii, putem sa conectam si coloane la variabile PHP pentru a fi populate automat cu ultimele date, de fiecare data cand se extrage un rand nou.
$sql="SELECT username, email FROM users";
$dataReader=$connection->createCommand($sql)->query();
// conectam prima coloana (username) cu variabila $username
$dataReader->bindColumn(1,$username);
// conectam a doua coloana (email) cu variabila $email
$dataReader->bindColumn(2,$email);
while($dataReader->read()!==false)
{
// $username si $email contin username si email din randul curent
}
Signup or Login in order to comment.