Inhaltsverzeichnis
Zend_Db_Adapter
ist die Datenbankabstraktionsschicht für das Zend
Framework. Basierend auf PDO kannst Du Zend_Db_Adapter
verwenden, um unter
Verwendung der gleichen API zu jedem der unterstützten SQL Datenbanksysteme eine
Verbindung aufzubauen bzw. damit zu arbeiten. Diese beinhalten Microsoft SQL Server,
MySQL, PostgreSQL, SQLite und andere.
Um eine Instanz von Zend_Db_Adapter
für dein spezielles Datenbank Backend
zu erstellen, mußt du Zend_Db::factory()
mit dem Namen des Adapters und
einem Array mit Parametern aufrufen, welche die Verbindung beschreiben. Hier ein
Beispiel für einen Verbindungsaufbau zu einer MySQL Datenbank mit Namen "camelot" auf
deinem lokalen Server als Benutzer mit Namen "malory":
<?php require_once 'Zend/Db.php'; $params = array ('host' => '127.0.0.1', 'username' => 'malory', 'password' => '******', 'dbname' => 'camelot'); $db = Zend_Db::factory('PDO_MYSQL', $params); ?>
Ähnlich erfolgt der Verbindungsaufbau zu einer SQlite Datenbank mit Namen "camelot.sq3":
<?php require_once 'Zend/Db.php'; $params = array ('dbname' => 'camelot.sq3'); $db = Zend_Db::factory('PDO_SQLITE', $params); ?>
Ähnlich erfolgt der Verbindungsaufbau zu einer SQLite2 Datenbank mit Namen "camelot.sq2": Für eine speicherbasierende SQlite Datenbank gebe keinen DSN Präfix an und verwende einen Datenbanknamen ":memory:".
<?php require_once 'Zend/Db.php'; $params = array ('dbname' => 'camelot.sq2', 'dsnprefix' => 'sqlite2'); $db = Zend_Db::factory('PDO_SQLITE', $params); ?>
So oder so kannst Du die exakt selbe API verwenden, um die Datenbank abzufragen.
Du solltest die Werte immer in Anführungszeichen setzen, die in einer SQL Anweisung
verwendet werden; dies hilft dabei, Attacken per SQL Injection zu vermeiden.
Zend_Db_Adapter
stellt zwei Methoden (über das zugrunde liegende PDO
Objekt) bereit, um dir zu helfen, werte manuell in Anführungszeichen zu setzen.
Die erste davon ist die quote()
Methode. Sie wird einen skalaren Wert
entsprechend für deinen Datenbank Adapter in Anführungszeichen setzen; wenn du
versuchst, ein Array in Anführungszeichen zu setzen, gibt es einen durch Komma
getrennten String mit den Arraywerten zurück, wobei jeder richtig in Anführungszeichen
gesetzt wird (dies ist hilfreich für Funktionen, die einen Listenparameter entgegen
kommen)).
<?php // Erstelle ein $db Objekt unter der Annahme eines Mysql Adapters // setze einen Skalar in Anführungszeichen $value = $db->quote('St John"s Wort'); // $value ist nun '"St John\"s Wort"' (beachte die umschließenden Anführungszeichen) // setze ein Array in Anführungszeichen $value = $db->quote(array('a', 'b', 'c'); // $value ist nun '"a", "b", "c"' (ein durch Komma getrennter String) ?>
Die zweite ist die quoteInto()
Methode. Du stellst einen Basisstring mit
einem Fragezeichen als Platzhalter bereit und dann einen Skalar oder ein Array, um es
in dem String mit Anführungszeichen zu versehen. Dies ist nützlich für die Konstruktion
von Abfragen oder Klauseln "as-you-go". Skalare und Arrays verhalten sich genauso wie
bei der quote()
Methode.
<?php // Erstelle ein $db Objekt unter der Annahme eines Mysql Adapters // setze einen Skalar in einer WHERE Klausel in Anführungszeichen $where = $db->quoteInto('id = ?', 1); // $where ist nun 'id = "1"' (beachte die umschließenden Anführungszeichen) // setze ein Array in einer WHERE Klausel in Anführungszeichen $where = $db->quoteInto('id IN(?)', array(1, 2, 3)); // $where ist nun 'id IN("1", "2", "3")' (ein durch Komma getrennter String) ?>
Sobald du eine Zend_Db_Adapter
Instanz hast, kannst du Abfragen direkt in
SQL ausführen. Zend_Db_Adapter
übergibt diese Abfragen an das zugrunde
liegende PDO Objekt, welches sie aufbereitet und ausführt, und gibt dann ein
PDOStatement Objekt zurück, um die Ergebnisse (soweit vorhanden) zu verarbeiten.
<?php // Erstelle ein $db Objekt und frage dann die Datenbank // mit einer korrekt quotierten SQL Abfrage ab. $sql = $db->quoteInto( 'SELECT * FROM example WHERE date > ?', '2006-01-01' ); $result = $db->query($sql); // verwende das PDOStatement $result, um alle Zeilen als Array zu erhalten $rows = $result->fetchAll(); ?>
Du kannst Daten automatisch mit einer Abfrage verbinden. Dies bedeutet, dass du mehrere benannte Platzhalter in der Abfrage setzen und dann ein Array mit den Daten übergeben kannst, welche diese Platzhalter ersetzen. Die ersetzten Werte werden für dich automatisch in Anführungszeichen gesetzt, um größere Sicherheit gegen Attacken per SQL Injection zu bieten.
<?php // Erstelle ein $db Objekt und frage dann die Datenbank ab. // Dieses Mal verwende Platzhalter. $result = $db->query( 'SELECT * FROM example WHERE date > :placeholder', array('placeholder' => '2006-01-01') ); // verwende das PDOStatement $result, um alle Zeilen als Array zu erhalten $rows = $result->fetchAll(); ?>
Optional möchtest du vielleicht Daten manuell aufbereiten und mit der SQL Abfrage
verbinden. Hierfür verwende die prepare()
Methode, um ein aufbereitetes
PDOStatement
zu erhalten, das du direkt verarbeiten kannst.
<?php // Erstelle ein $db Objekt und frage dann die Datenbank ab. // Dieses Mal bereite ein PDOStatement auf für das manuelle Verbinden. $stmt = $db->prepare('SELECT * FROM example WHERE date > :placeholder'); $stmt->bindValue('placeholder', '2006-01-01'); $stmt->execute(); // verwende das PDOStatement $result, um alle Zeilen als Array zu erhalten $rows = $stmt->fetchAll(); ?>
Standardmäßig sind PDO (und damit auch Zend_Db_Adapter
) im "auto-commit"
Modus. Das heißt, dass alle Abfragen abgearbeitet werden, wenn sie ausgeführt werden.
Wenn du sie innerhalb einer Transaktion ausführen möchtest, rufe einfach die
beginTransaction()
Methode auf und danach entweder commit()
oder rollBack()
für deine Änderungen. Zend_Db_Adapter
kehrt
in den "auto-commit" Modus zurück, bis du beginTransaction()
wieder
aufrufst.
<?php // Erstelle ein $db Objekt und starte dann eine Transaktion $db->beginTransaction(); // Versuche eine Abfrage // wenn erfolgreich, verarbeite die Änderungen // wenn nicht erfolgreich, setze Änderungen zurück try { $db->query(...); $db->commit(); } catch (Exception $e) { $db->rollBack(); echo $e->getMessage(); } ?>
Der Einfachheit halber kannst du die insert()
Methode verwenden, um für
dich eine INSERT Anweisung zu erstellen und mit den einzufügenden Daten zu verknüpfen.
(Die verknüpften Daten werden automatisch in Anführungszeichen gesetzt, um Attacken per
SQL Injection zu vermeiden.)
Der Rückgabewert ist nicht die zuletzt eingefügte ID, da eine
Tabelle keine automatisch inkrementierte Spalte haben muß. Stattdessen enthält der
Rückgabewert die Zahl der beeinflussten Zeilen (normalerweise 1). Wenn du die ID des
zuletzt eingefügten Datensatzes haben möchtest, rufe die lastInsertId()
Methode nach dem Einfügen auf.
<?php // // INSERT INTO round_table // (noble_title, first_name, favorite_color) // VALUES ("King", "Arthur", "blue"); // // Erstelle ein $db Objekt und dann... // die einzufügenden Daten im Spalte => Wert Format $row = array ( 'noble_title' => 'King', 'first_name' => 'Arthur', 'favorite_color' => 'blue', ); // die Tabelle, in der die Daten eingefügt werden sollen $table = 'round_table'; // füge die Daten ein und hole die ID der eingefügten Zeile $rows_affected = $db->insert($table, $row); $last_insert_id = $db->lastInsertId(); ?>
Der Einfachheit halber kannst du die update()
Methode verwenden, um für
dich eine UPDATE Anweisung zu erstellen und mit den zu aktualisierenden Daten zu
verknüpfen. (Die verknüpften Daten werden automatisch in Anführungszeichen gesetzt, um
Attacken per SQL Injection zu vermeiden.)
Du kannst eine optionale WHERE Klausel übergeben um anzugeben, welche Zeilen aktualisiert werden sollen. (Beachte, dass die WHERE Klausel kein verknüpfter Parameter ist, so dass du die Werte selber in Anführungszeichen setzen musst.)
<?php // // UPDATE round_table // SET favorite_color = "yellow" // WHERE first_name = "Robin"; // // Erstelle ein $db Objekt und dann... // die neuen Werte, die aktualisiert werden sollen, im Spalte => Wert Format. $set = array ( 'favorite_color' => 'yellow', ); // die zu aktualisierende Tabelle $table = 'round_table'; // die WHERE Klausel $where = $db->quoteInto('first_name = ?', 'Robin'); // aktualisiere die Tabelle und hole die Anzahl der beeinflussten Zeilen $rows_affected = $db->update($table, $set, $where); ?>
Der Einfachheit halber kannst du die delete()
Methode verwenden, um für
dich eine DELETE Anweisung zu erstellen. Du kannst eine optionale WHERE Klausel
übergeben um anzugeben, welche Zeilen gelöscht werden sollen. (Beachte, dass die WHERE
Klausel kein verknüpfter Parameter ist, so dass du die Werte selber in
Anführungszeichen setzen musst.)
<?php // // DELETE FROM round_table // WHERE first_name = "Patsy"; // // Erstelle ein $db Objekt und dann... // die Tabelle, aus der gelöscht werden soll $table = 'round_table'; // die WHERE Klausel $where = $db->quoteInto('first_name = ?', 'Patsy'); // aktualisiere die Tabelle und hole die Anzahl der beeinflussten Zeilen $rows_affected = $db->delete($table, $where); ?>
Obwohl du die Datenbank direkt mit der query()
Methode abfragen kannst,
wirst du häufig nur Zeilen selektieren und die Ergebnisse zurückerhalten wollen. Der
Satz von fetch*()
Methoden macht dies für dich. Für jede der
fetch*()
Methoden, übergibst du eine SQL SELECT Anweisung; wenn du
benannte Platzhalter in der Anweisung verwendest, kannst du zudem ein Array mit zu
verknüpfenden Werte übergeben, die in Anführungszeichen gesetzt und in der Anweisung
ausgetauscht werden. Die fetch*()
Methoden lauten:
fetchAll()
fetchAssoc()
fetchCol()
fetchOne()
fetchPairs()
fetchRow()
<?php // Erstelle ein $db Objekt und dann... // hole alle Spalten aller Zeilen als sequentielles Array $result = $db->fetchAll( "SELECT * FROM round_table WHERE noble_title = :title", array('title' => 'Sir') ); // hole alle Spalten aller Zeilen als assoziatives Array // die erste Splate wird als Array Schlüssel verwendet $result = $db->fetchAssoc( "SELECT * FROM round_table WHERE noble_title = :title", array('title' => 'Sir') ); // hole die erste Splate aller Zeilen $result = $db->fetchCol( "SELECT first_name FROM round_table WHERE noble_title = :title", array('title' => 'Sir') ); // hole nur den ersten Wert $result = $db->fetchOne( "SELECT COUNT(*) FROM round_table WHERE noble_title = :title", array('title' => 'Sir') ); // hole einen Satz von Schlüssel-Wert Paaren; die erste Spalte ist // der Array Schlüssel, die zweite Spalte ist der Array Wert $result = $db->fetchPairs( "SELECT first_name, favorite_color FROM round_table WHERE noble_title = :title", array('title' => 'Sir') ); // hole nur die erste Zeile $result = $db->fetchRow( "SELECT * FROM round_table WHERE first_name = :name", array('name' => 'Lancelot') ); ?>