Data Access Objects (DAO)

Data Access Objects (DAO) tilbyr et API for å aksessere data lagret i ulike databasesystemer (DBMS). Som et resultat av dette kan underliggende databasesystem byttes ut uten å endre koden som benytter DAO for å aksessere dataene.

DAO i Yii benytter PHP Data Objects (PDO) som er et tillegg til PHP som tilbyr et generelt grensesnitt for mange populære databasesystemer slik som MySQL og PostgreSQL. Derfor må PDO-tillegget og nødvendige PDO-drivere (for eksempel: PDO_MYSQL) være installert.

DAO i Yii består i hovedsak av følgende fire klasser:

Videre ser vi litt på bruken av DAO i Yii.

Etablere en databasetilkobling

For å etablere en databasetilkobling må du opprette en instans av CDbConnection og aktivere den. Et navn på datakilden (DSN) er påkrevet for å koble til databasen. Et brukernavn og passord kan også være nødvendig for å etablere tilkoblingen. Dersom tilkoblingen feiler får du en feilmelding (for eksempel: feil DSN eller ugyldig brukernavn/passord).

$connection = new CDbConnection($dsn,$username,$password);
// etablerer tilkoblingen. Her kan du bruke try...catch for å håndtere feil
$connection->active = true;
......
$connection->active = false;  // lukk tilkoblingen

Formatet på DSN avhenger av PDO-driveren som benyttes. Generelt inneholder DSN navnet på PDO-driveren etterfulgt av kolon etterfulgt av driver-spesifikk syntaks for tilkoblingen. Se PDO dokumentasjonen for komplett informasjon. Her er noen eksempler:

Siden CDbConnection arver CApplicationComponent kan du også bruke den som en appkilasjonskomponent For å få til dette må db-komponenten i konfigurasjonsfilen for applikasjonen defineres slik:

array(
    ......
    'components' => array(
        ......
        'db' => array(
            'class' => 'CDbConnection',
            'connectionString' => 'mysql:host=localhost;dbname=testdb',
            'username' => 'root',
            'password' => 'password',
        ),
    ),
)

Da kan du aksessere databasetilkoblingen via Yii::app()->db som allerede er aktivert (med mindre du eksplisitt setter CDbConnection::autoConnect til false). Ved å bruke denne teknikken kan samme databasetilkobling deles mange steder i koden.

Utføre spørringer

Når du har etablert tilkoblingen til databasen kan du kjøre spørringer ved hjelp av CDbCommand. Du oppretter en instans av CDbCommand ved å kjøre CDbConnection::createCommand() med et SQL-uttrykk:

$command = $connection->createCommand($sql);
// ved behov kan du også oppdatere SQL-uttrykket ditt slik:
// $command->text = $newSQL;

Du utfører et SQL-uttrykk via CDbCommand på en av følgende to måter:

Dersom en feil opptrer under kjøring av et SQL-uttrykk kastes en exception.

$rowCount = $command->execute();   // utfører et SQL-uttrykk som ikke er en spørring
$dataReader = $command->query();   // utfører en SQL-spørring
$rows = $command->queryAll();      // utfører en spørring og returnerer alle rader
$row = $command->queryRow();       // utfører en spørring og returnerer første rad
$column = $command->queryColumn(); // utfører en spørring og returnerer første kolonne
$value = $command->queryScalar();  // utfører en spørring og returnerer første felt i første rad

Hente ut resultatet av en spørring

Når CDbCommand::query() har returnert CDbDataReader-instansen kan du hente ut rader fra resultatsettet ved å kalle CDbDataReader::read() gjenntatte ganger. Du kan også bruke CDbDataReader i en foreach-løkke for å hente ut rad for rad.

$dataReader = $command->query();
 
// kjør read() gjenntatte ganger helt til den returnerer "false"
while(($row = $dataReader->read()) !== false) { ... }
 
// eller bruk en foreach-løkke for å iterere igjennom hver rad i datasettet
foreach($dataReader as $row) { ... }
 
// eller hent ut alle rader direkte og lagre de i et array
$rows = $dataReader->readAll();

Merk: I motsetning til query() returnerer alle queryXXX() metoder data direkte. For eksempel returnerer queryRow() første rad fra resultatet.

Transaksjoner

Når en applikasjon utfører et par spørringer som hver seg henter og/eller skriver informasjon til databasen er det viktig å passe på at alle spørringene blir kjørt riktig. En transaksjon (representert ved en CDbTransaction-instans i Yii) kan brukes slik:

Dette kan implementeres med følgende kode:

$transaction = $connection->beginTransaction();
 
try
{
    $connection->createCommand($sql1)->execute();
    $connection->createCommand($sql2)->execute();
    //.... flere spørringer
    $transaction->commit();
}
catch(Exception $e) // en "exception" kastes dersom en spørring feiler
{
    $transaction->rollBack();
}

Kobling av variable

For å unngå såkalte SQL-injeksjons angrep og for å øke ytelsen på SQL-uttrykk som gjenntas flere ganger kan du "forberede" et SQL-uttrykk med markører som byttes ut med faktiske variable.

Markørene for variablene kan enten defineres med unike navn eller med et spørsmålstegn. Kall CDbCommand::bindParam() eller CDbCommand::bindValue() for å bytte ut disse markørene med faktiske variable. Du trenger ikke tenke på å bytte ut reserverte tegn (slik som anførselstegn) da den underliggende databasedriveren håndterer dette for deg. Bindingen mellom markører og variable må defineres før SQL'en kjøres.

// en uttrykk med to markører ":username" og ":email"
$sql = "INSERT INTO users(username, email) VALUES(:username,:email)";
$command = $connection->createCommand($sql);
 
// bytt ut markøren ":username" med det faktiske brukernavnet
$command->bindParam(":username", $username, PDO::PARAM_STR);
 
// bytt ut markøren ":email" med den faktiske e-postadressen
$command->bindParam(":email", $email, PDO::PARAM_STR);
$command->execute();
 
// sett inn en rad til med et nytt sett med variable
$command->bindParam(":username", $username2, PDO::PARAM_STR);
$command->bindParam(":email", $email2, PDO::PARAM_STR);
$command->execute();

Metodene bindParam() og bindValue() er veldig like. Den eneste forskjellen er at den første kobler variable med en referanse til en PHP variabel, mens den siste med verdien av en PHP variabel. For variable som inneholder store mengder data anbefales det å bruke den første.

For flere detaljer om kobling av variable se PHP-manualen.

Kobling av kolonner

Du kan også koble kolonner i et resultatsett med variabler i PHP slik at de automatisk oppdateres hver gang du henter ut en rad.

$sql = "SELECT username, email FROM users";
$dataReader = $connection->createCommand($sql)->query();
 
// koble første kolonne (username) med variabelen $username
$dataReader->bindColumn(1, $username);
 
// koble andre kolonne (email) med variabelen $email
$dataReader->bindColumn(2, $email);
 
while($dataReader->read() !== false)
{
    // $username og $email inneholder brukernavnet og e-postadressen for den gjeldene raden
}
$Id: database.dao.txt 857 2009-03-20 17:31:09Z qiang.xue $