Data Access Objects (DAO)

Data Access Objects (Datenzugriffsobjekte, DAO) bieten eine einheitliche Schnittstelle für den Zugriff auf unterschiedliche Datenbanksysteme (DMBS). Verwendet man DAO, kann auf ein anderes DBMS umgestellt werden, ohne den entsprechenden Code ändern zu müssen.

Yii DAO basieren auf den PHP Data Objects (PDO). Diese PHP-Erweiterung ermöglicht vereinheitlichten Zugriff auf viele bekannte DMBS, wie z.B. MySQL und PostgreSQL. Möchte man Yii DAO verwenden, muss daher die PDO-Erweiterung und die entsprechenden PDO-Datenbanktreiber (z.B. PDO_MYSQL) installiert sein.

Yii DAO besteht im Wesentlichen aus den folgenden vier Klassen:

In den folgenden Abschnitten zeigen wir, wie man mit DAO arbeitet.

Aufbauen einer Datenbankverbindung

Um eine Verbindung zur Datenbank aufzubauen, muss eine CDbConnection-Instanz erzeugt und aktiviert werden. Die Anmeldeinformationen werden dabei in Form eines DSN (Data Source Name) angegeben. Auch Benutzername und Passwort können erforderlich sein. Tritt während des Verbindungsaufbaus ein Fehler auf (weil z.B. der DSN ungültig oder Benutzername bzw. Passwort falsch waren), wird eine Exception ausgelöst.



Das DSN-Format hängt vom benutzten PDO-Datenbanktreiber ab. Im Allgemeinen enthält ein DSN den PDO-Treibernamen, gefolgt von einem Doppelpunkt, gefolgt von der treiberspezifischen Verbindungssyntax. Nähere Informationen finden Sie in der PDO-Dokumentation. Die gebräuchlichsten DSN-Formate sind:

Da CDbConnection von CApplicationComponent abgeleitet ist, kann man sie auch als Anwendungskomponente verwenden. Dazu erstellt man in der Anwendungskonfiguration eine Komponente db (die allerdings auch beliebig anders heißen kann):



Über Yii::app()->db kann man dann auf eine bereits aktivierte Verbindung zugreifen, es sei denn, CDbConnection::autoConnect wurde auf false gesetzt. Auf diese Weise steht in der gesamten Anwendung die selbe DB-Verbindung zur Verfügung.

Ausführen von SQL-Anweisungen

Steht die Datenbankverbindung, kann man mit Hilfe von CDbCommand SQL-Anweisungen ausführen. Eine CDbCommand-Instanz wird erzeugt, indem man CDbConnection::createCommand() mit der entsprechenden SQL-Anweisung aufruft:



Die Anweisung wird beim Aufruf einer dieser CDbCommand-Methoden ausgeführt:

Tritt bei der Ausführung ein Fehler auf, wird eine Exception ausgelöst.



Auslesen von Abfrageergebnissen

Hat man von CDbCommand::query() eine Instanz von CDbDataReader zurückerhalten, kann man die einzelnen Ergebniszeilen durch wiederholten Aufruf von CDbDataReader::read() abfragen. Auch der Einsatz in einer foreach-Schleife ist möglich:



Hinweis: Anders als query() liefern alle queryXXX()-Methoden die Daten direkt zurück. Zum Beispiel liefert queryRow() ein Array mit den Daten der ersten Zeile des Abfrageergebnisses.

Verwenden von Transaktionen

Wenn eine Anwendung mehrere lesende und/oder schreibende Anweisungen ausführt, ist es wichtig, dass die Datenbank am Ende nicht in einem inkonsistenten Zustand verbleibt, weil nicht alle Anweisungen erfolgreich abgeschlossen werden konnten. Zu diesem Zweck leitet man am besten eine Transaktion ein, die in Yii durch eine Instanz von CDbTransaction repräsentiert wird.

Diesen Ablauf kann man in Yii so implementieren:



Binden von Parametern

Um Angriffe wie SQL-Injection zu vermeiden und um mehrfach auszuführende SQL-Anweisungen zu beschleunigen, kann man eine Anweisung "vorbereiten" (engl. prepare), die optional auch Platzhalter für Parameter enthalten kann. Beim sogenannten "Binden" werden diese Platzhalter dann durch die eigentlichen Parameterwerte ersetzt.

Platzhalter können entweder aus einer eindeutigen Zeichenkette oder einem Fragezeichen bestehen. Mit CDbCommand::bindParam() oder CDbCommand::bindValue() werden die eigentlichen Parameter an die Stelle der Platzhalter gesetzt. Sonderzeichen in diesen Parametern bedürfen dabei keiner speziellen Beachtung. Der zugrundeliegende Datenbanktreiber kümmert sich automatisch um deren korrekte und sichere Verarbeitung. Dieses Binden muss vor dem Ausführen der Anweisung erfolgen.



Der einzige Unterschied zwischen den erwähnten Befehlen besteht darin, dass bindValue() einen konkreten Wert an einen Platzhalter bindet, während bindParam() den Platzhalter an eine Referenz auf eine PHP-Variable bindet. Bei umfangreichen Parameterdaten ist letzteres aus Performancegründen zu bevorzugen.

Weitere Einzelheiten zum Binden von Parametern finden Sie in der entsprechenden PHP Dokumentation.

Binden von Spalten

Man kann auch ganze Spalten aus einem Abfrageergebnis an PHP Variablen binden. Bei jedem Zugriff auf eine Zeile sind diese Variablen dann automatisch mit den aktuellen Zeilendaten befüllt.



Verwenden eines Tabellenpräfix

Ein Tabellenpräfix wird allen Tabellennamen der aktuellen Verbindung vorangestellt. Es wird meist in gemeinsam genutzten Hosting-Umgebungen verwendet, wo mehrere Anwendungen sich eine einzelne Datenbank teilen und zur Unterscheidung eben verschiedene Präfixe verwenden. Eine Anwendung könnte z.B. tbl_, eine andere yii_ vor alle Tabellennamen stellen.

Ein Tabellenpräfix wird über die Eigenschaft CDbConnection::tablePrefix konfiguriert. In SQL-Ausdrücken kann man dann {{TabellenName}} statt des Tabellennamens verwenden, wobei TabellenName dem Namen ohne Präfix entspricht. Wenn die Datenbank z.B. eine Tabelle tbl_user enthält und tbl_ als Tabellenpräfix konfiguriert wurde, kann eine Anfrage so aussehen:



$Id: database.dao.txt 2890 2011-01-18 15:58:34Z qiang.xue $