| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- EN-Revision: 15851 -->
- <!-- Reviewed: no -->
- <sect1 id="zend.db.adapter">
- <title>Zend_Db_Adapter</title>
- <para>
- <classname>Zend_Db</classname> und die zugehörigen Klassen bieten eine einfache SQL
- Schnittstelle für Zend Framework. <classname>Zend_Db_Adapter</classname> ist die Basisklasse
- zur Anbindung einer PHP Anwendung an ein RDBMS. Es gibt für jede RDBMS Marke einen eigenen
- Adapter.
- </para>
- <para>
- Die <classname>Zend_Db</classname> Adapter bilden eine Schnittstelle zu den Hersteller
- spezifischen PHP Erweiterungen und unterstützen dadurch die Entwicklung einer PHP Anwendung
- für verschiedene RDBMS mit geringem Aufwand.
- </para>
- <para>
- Die Schnittstellen der Adapterklasse ähneln denen der
- <ulink url="http://www.php.net/pdo">PHP Data Objects</ulink> Erweiterung.
- <classname>Zend_Db</classname> bietet Adapterklassen für PDO Treiber der folgenden RDBMS
- Marken:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- IBM DB2 und Informix Dynamic Server (IDS), verwenden die
- <ulink url="http://www.php.net/pdo-ibm">pdo_ibm</ulink> PHP Erweiterung
- </para>
- </listitem>
- <listitem>
- <para>
- MySQL, verwendet die <ulink url="http://www.php.net/pdo-mysql">pdo_mysql</ulink> PHP
- Erweiterung
- </para>
- </listitem>
- <listitem>
- <para>
- Microsoft SQL Server, verwendet die <ulink
- url="http://www.php.net/pdo-mssql">pdo_mssql</ulink> PHP Erweiterung
- </para>
- </listitem>
- <listitem>
- <para>
- Oracle, verwendet die <ulink url="http://www.php.net/pdo-oci">pdo_oci</ulink> PHP
- Erweiterung
- </para>
- </listitem>
- <listitem>
- <para>
- PostgreSQL, verwendet die <ulink
- url="http://www.php.net/pdo-pgsql">pdo_pgsql</ulink> PHP Erweiterung
- </para>
- </listitem>
- <listitem>
- <para>
- SQLite, verwendet die <ulink url="http://www.php.net/pdo-sqlite">pdo_sqlite</ulink>
- PHP Erweiterung
- </para>
- </listitem>
- </itemizedlist>
- <para>
- Zusätzlich bietet <classname>Zend_Db</classname> Adapterklassen für die folgenden Marken,
- welche eigene PHP Datenbank Erweiterungen nutzen:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- MySQL, mit der <ulink url="http://www.php.net/mysqli">mysqli</ulink> PHP Erweiterung
- </para>
- </listitem>
- <listitem>
- <para>
- Oracle, mit der <ulink url="http://www.php.net/oci8">oci8</ulink> PHP Erweiterung
- </para>
- </listitem>
- <listitem>
- <para>
- IBM DB2 und DB2/i5, mit der <ulink url="http://www.php.net/ibm_db2">ibm_db2</ulink>
- PHP Erweiterung
- </para>
- </listitem>
- <listitem>
- <para>
- Firebird/Interbase, mit der <ulink
- url="http://www.php.net/ibase">php_interbase</ulink> PHP Erweiterung
- </para>
- </listitem>
- </itemizedlist>
- <note>
- <para>
- Jeder <classname>Zend_Db</classname> Adapter nutzt eine PHP Erweiterung. Die
- entsprechend PHP Erweiterung muss in der PHP Umgebung aktiviert sein um den
- <classname>Zend_Db</classname> Adapter zu nutzen. Zum Beispiel muss bei der Nutzung
- eines PDO <classname>Zend_Db</classname> Adapters sowohl die PDO Erweiterung, als auch
- der PDO Treiber für die jeweilige Marke geladen sein.
- </para>
- </note>
- <sect2 id="zend.db.adapter.connecting">
- <title>Anbindung einer Datenbank mit einem Adapter</title>
- <para>
- Dieser Abschnitt beschreibt wie eine Instanz eines Datenbankadapters erzeugt wird. Dies
- entspricht der Erzeugung einer Verbindung an ein RDBMS Server in einer PHP Anwendung.
- </para>
- <sect3 id="zend.db.adapter.connecting.constructor">
- <title>Nutzung des Zend_Db Adapter Konstruktors</title>
- <para>
- Man kann eine Instanz eines Adapters erzeugen, indem man den Konstruktor verwendet.
- Ein Adapter Konstruktur benötigt ein Argument, wobei es sich um ein Array mit
- Parametern für die Verbindung handelt.
- </para>
- <example id="zend.db.adapter.connecting.constructor.example">
- <title>Nutzung eines Adapter Konstruktors</title>
- <programlisting language="php"><![CDATA[
- $db = new Zend_Db_Adapter_Pdo_Mysql(array(
- 'host' => '127.0.0.1',
- 'username' => 'webuser',
- 'password' => 'xxxxxxxx',
- 'dbname' => 'test'
- ));
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.connecting.factory">
- <title>Nutzung der Zend_Db Factory</title>
- <para>
- Als Alternative zur direkten Nutzung des Konstruktors kann man auch eine Instanz des
- Adapters erzeugen indem man die statische Methode
- <classname>Zend_Db::factory()</classname> nutzt. Diese Methode lädt die
- Adapterklasse dynamisch bei Aufruf unter Nutzung von <link
- linkend="zend.loader.load.class">Zend_Loader::loadClass()</link>.
- </para>
- <para>
- Das erste Argument ist ein String der den Namen der Adapterklasse enthält. Zum
- Beispiel entspricht der String 'Pdo_Mysql' der Klasse Zend_Db_Adapter_Pdo_Mysql. Das
- zweite Argument ist das gleiche Array von Parametern wie bei der Verwendung des
- Adapter Konstruktors.
- </para>
- <example id="zend.db.adapter.connecting.factory.example">
- <title>Nutzung der Adapter factory() Methode</title>
- <programlisting language="php"><![CDATA[
- // Wir benötigen das folgende Statement nicht da die
- // Zend_Db_Adapter_Pdo_Mysql Datei für uns durch die Factory
- // Methode von Zend_Db geladen wird
- // require_once 'Zend/Db/Adapter/Pdo/Mysql.php';
- // Lädt automatisch die Klasse Zend_Db_Adapter_Pdo_Mysql
- // und erzeugt eine Instanz von Ihr.
- $db = Zend_Db::factory('Pdo_Mysql', array(
- 'host' => '127.0.0.1',
- 'username' => 'webuser',
- 'password' => 'xxxxxxxx',
- 'dbname' => 'test'
- ));
- ]]></programlisting>
- </example>
- <para>
- Wenn eine eigene Klasse geschrieben wird, die
- <classname>Zend_Db_Adapter_Abstract_Adapter</classname> erweitert aber nicht mit dem
- Präfix "Zend_Db_Adapter" beginnt, kann die <code>factory()</code> Methode verwendet
- werden um den Adapter zu Laden wenn der führende Teil der Adapter Klasse mit dem
- 'adapterNamespace' Schlüssel im Parameter Array spezifiziert wird.
- </para>
- <example id="zend.db.adapter.connecting.factory.example2">
- <title>Die factory Methode für eine eigene Adapter Klasse verwenden</title>
- <programlisting language="php"><![CDATA[
- // Wir müssen die Datei der Adapter Klasse nicht laden
- // weil Sie für uns durch die Factory Methode von Zend_Db geladen wird
- // Die MyProject_Db_Adapter_Pdo_Mysql Klasse automatisch laden
- // und eine Instanz von Ihr erstellen.
- $db = Zend_Db::factory('Pdo_Mysql', array(
- 'host' => '127.0.0.1',
- 'username' => 'webuser',
- 'password' => 'xxxxxxxx',
- 'dbname' => 'test',
- 'adapterNamespace' => 'MyProject_Db_Adapter'
- ));
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.connecting.factory-config">
- <title>Zend_Config mit Zend_Db_Factory verwenden</title>
- <para>
- Optional kann jedes Argument der <code>factory()</code> Methode als Objekt des Typs
- <link linkend="zend.config">Zend_Config</link> spezifiziert werden.
- </para>
- <para>
- Wenn das erste Argument ein Config Objekt ist, wird erwartet das es eine Eigenschaft
- enthält die <code>adapter</code> heißt und einen String enthält der nach dem Adapter
- Basis Klassen Namen benannt ist. Optional kann das Objekt eine Eigenschaft genannt
- <code>params</code> enthalten, mit Subeigenschaften korrespondierend zu den
- Parameter Namen des Adapters. Das wird nur verwendet wenn das zweite Argument für
- die <code>factory()</code> Methode nicht angegeben wird.
- </para>
- <example id="zend.db.adapter.connecting.factory.example1">
- <title>
- Verwenden der Factory Methode des Adapters mit einem Zend_Config Objekt
- </title>
- <para>
- Im Beispiel anbei wird ein <classname>Zend_Config</classname> Objekt von einem
- Array erstellt. Die Daten können auch aus einer externen Datei geladen werden
- indem Klassen wie zum Beispiel <link
- linkend="zend.config.adapters.ini">Zend_Config_Ini</link> oder <link
- linkend="zend.config.adapters.xml">Zend_Config_Xml</link> verwendet werden.
- </para>
- <programlisting language="php"><![CDATA[
- $config = new Zend_Config(
- array(
- 'database' => array(
- 'adapter' => 'Mysqli',
- 'params' => array(
- 'host' => '127.0.0.1',
- 'dbname' => 'test',
- 'username' => 'webuser',
- 'password' => 'secret',
- )
- )
- )
- );
- $db = Zend_Db::factory($config->database);
- ]]></programlisting>
- </example>
- <para>
- Das zweite Argument der <code>factory()</code> Methode kann ein assoziatives Array
- sein das Einträge enthält die den Parameters des Adapters entsprechen. Dieses
- Argument ist optional. Wenn das erste Argument vom Typ
- <classname>Zend_Config</classname> ist, wird angenommen das es alle Parameter
- enthält, und das zweite Argument wird ignoriert.
- </para>
- </sect3>
- <sect3 id="zend.db.adapter.connecting.parameters">
- <title>Adapter Parameter</title>
- <para>
- Die folgende Liste erklärt die gemeinsamen Parameter die von
- <classname>Zend_Db</classname> Adapterklassen erkannt werden.
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>host</emphasis>:
- Ein String der den Hostname oder die Ip-Adresse des Datenbankservers
- beinhaltet. Wenn die Datenbank auf dem gleichen Host wie die PHP Anwendung
- läuft wird 'localhost' oder '127.0.0.1' verwendet.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>username</emphasis>:
- Konto Kennung zur Authentisierung einer Verbindung zum RDBMS Server.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>password</emphasis>:
- Konto Passwort zur Authentisierung einer Verbindung zum RDBMS Server.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>dbname</emphasis>:
- Datenbank Name auf dem RDBMS Server.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>port</emphasis>:
- Einige RDBMS Server können Netzwerkverbindungen an vom Administrator
- spezifizierten Ports akzeptieren. Der Port-Parameter gibt die Möglichkeit
- die Portnummer anzugeben, an welche die PHP Anwendung verbindet um der
- Port-Konfiguration des RDBMS Servers zu entsprechen.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>options</emphasis>:
- Dieser Parameter ist ein assoziatives Array von Optionen die in allen
- Zend_Db_Adapter Klassen enthalten sind.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>driver_options</emphasis>: Dieser Parameter ist ein assoziatives
- Array von zusätzlichen Optionen die spezifisch für die angegebene
- Datenbankerweiterung sind. Eine typische Anwendung dieses Parameters ist,
- Attribute für einen PDO Treiber zu setzen.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>adapterNamespace</emphasis>:
- Benennt den führenden Teil des Klassen Namens für den Adapter statt
- 'Zend_Db_Adapter'. Dies kann verwendet werden wenn man die
- <code>factory()</code>Methode verwenden muß um eine nicht von Zend kommende
- Datenbank Adapter Klasse zu laden.
- </para>
- </listitem>
- </itemizedlist>
- <example id="zend.db.adapter.connecting.parameters.example1">
- <title>Übergeben der case-folding Option an die factory</title>
- <para>
- Diese Option kann über die Konstante
- <classname>Zend_Db::CASE_FOLDING</classname> angegeben werden. Sie entspricht
- dem <code>ATTR_CASE</code> Attribut in PDO and IBM DB2 Datenbanktreibern und
- stelllt die Schreibweise von String Schlüsseln in Abfrageergebnissen ein. Die
- Option kann den Wert <classname>Zend_Db::CASE_NATURAL</classname>
- (der Standard), <classname>Zend_Db::CASE_UPPER</classname> oder
- <classname>Zend_Db::CASE_LOWER</classname> annehmen.
- </para>
- <programlisting language="php"><![CDATA[
- $options = array(
- Zend_Db::CASE_FOLDING => Zend_Db::CASE_UPPER
- );
- $params = array(
- 'host' => '127.0.0.1',
- 'username' => 'webuser',
- 'password' => 'xxxxxxxx',
- 'dbname' => 'test',
- 'options' => $options
- );
- $db = Zend_Db::factory('Db2', $params);
- ]]></programlisting>
- </example>
- <example id="zend.db.adapter.connecting.parameters.example2">
- <title>Übergeben der auto-quoting Option an die factory</title>
- <para>
- Diese Option kann über die Konstante
- <classname>Zend_Db::AUTO_QUOTE_IDENTIFIERS</classname> angegeben werden. Wenn
- der Wert <constant>TRUE</constant> (der Standard) ist, werden Bezeichner wie
- Tabellennamen, Spaltennamen und auch Aliase in jeder SQL Syntax die vom Adapter
- Objekt generiert wurde begrenzt. Dies macht es einfach Bezeichner zu verwenden,
- die SQL Schlüsselwörter oder spezielle Zeichen enthalten. Wenn der Wert
- <constant>FALSE</constant> ist, werden Bezeichner nicht automatisch begrenzt. Wenn
- Bezeichner begrenzt werden müssen, so kann dies über die
- <code>quoteIdentifier()</code> Methode von Hand getan werden.
- </para>
- <programlisting language="php"><![CDATA[
- $options = array(
- Zend_Db::AUTO_QUOTE_IDENTIFIERS => false
- );
- $params = array(
- 'host' => '127.0.0.1',
- 'username' => 'webuser',
- 'password' => 'xxxxxxxx',
- 'dbname' => 'test',
- 'options' => $options
- );
- $db = Zend_Db::factory('Pdo_Mysql', $params);
- ]]></programlisting>
- </example>
- <example id="zend.db.adapter.connecting.parameters.example3">
- <title>Übergeben von PDO Treiber Optionen an die factory</title>
- <programlisting language="php"><![CDATA[
- $pdoParams = array(
- PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true
- );
- $params = array(
- 'host' => '127.0.0.1',
- 'username' => 'webuser',
- 'password' => 'xxxxxxxx',
- 'dbname' => 'test',
- 'driver_options' => $pdoParams
- );
- $db = Zend_Db::factory('Pdo_Mysql', $params);
- echo $db->getConnection()
- ->getAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY);
- ]]></programlisting>
- </example>
- <example id="zend.db.adapter.connecting.parameters.example4">
- <title>Übergabe einer Serialisierungs Option an die Factory</title>
- <programlisting language="php"><![CDATA[
- $options = array(
- Zend_Db::ALLOW_SERIALIZATION => false
- );
- $params = array(
- 'host' => '127.0.0.1',
- 'username' => 'webuser',
- 'password' => 'xxxxxxxx',
- 'dbname' => 'test',
- 'options' => $options
- );
- $db = Zend_Db::factory('Pdo_Mysql', $params);
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.connecting.getconnection">
- <title>Verwalten von Lazy Connections</title>
- <para>
- Die Erzeugung einer Instanz der Adapterklasse stellt nicht gleichzeitig eine
- Verbindung zum RDBMS her. Der Adapter speichert die Verbindungsparameter und stellt
- die tatsächliche Verbindung bei Bedarf her, wenn die erste Anfrage ausgeführt wird.
- Dies stellt sicher, dass die Erzeugung eines Adapterobjekts schnell und sparsam ist.
- Dadurch kann auch dann eine Instanz eines Adapters erzeugt werden, wenn nicht
- zwingend eine Datenbankanfrage für die aktuell gelieferte Darstellung der Anwendung
- benötigt wird.
- </para>
- <para>
- Wenn der Adapter zwingend eine Verbindung zum RDBMS herstellen soll, kann die
- <code>getConnection()</code> Methode verwendet werden. Diese liefert ein Objekt der
- Verbindung, welches eine Verbindung entsprechend der verwendeten PHP Erweiterung
- repräsentiert. Wenn zum Beispiel irgendeine der PDO Adapterklassen verwendet wird,
- dann liefert <code>getConnection()</code> das PDO Object, nachdem es als eine live
- Verbindung zu der entsprechenden Datenbank initialisiert wurde.
- </para>
- <para>
- Es kann nützlich sein eine Verbindung zu erzwingen um jegliche Exceptions
- abzufangen, die als Resultat falscher Konto Berechtigungen oder einem anderen Fehler
- bei der Verbindung zum RDBMS auftreten. Diese Exceptions treten nicht auf, bis die
- tatsächliche Verbindung hergestellt ist, daher kann es den Anwendungs-Code
- vereinfachen, wenn diese Exceptions an einer Stelle bearbeitet werden, und nicht
- erst bei der ersten Anfrage.
- </para>
- <para>
- Zusätzlich kann ein Adapter serialisiert werden um Ihn zu speichern, zum Beispiel in
- einer Session Variable. Das kann sehr nütlich sein, nicht nur für den Adapter
- selbst, sondern auch für andere Objekte die Ihn verwenden, wie ein
- <classname>Zend_Db_Select</classname> Objekt. Standardmäßig, ist es Adaptern erlaubt
- serialisiert zu werden. Wenn man das nicht will, sollte man die
- <classname>Zend_Db::ALLOW_SERIALIZATION=false</classname> Option übergeben, wie im
- Beispiel anbei gezeigt. Um das Prinzip von Lazy Connections zu erlauben, wird der
- Adapter sich selbst nicht wiederverbinden wenn er deserialisiert wird. Man muß
- <code>getConnection()</code> selbst aufrufen. Mann kann den Adapter dazu bringen
- sich automatisch wieder zu verbinden indem
- <classname>Zend_Db::AUTO_RECONNECT_ON_UNSERIALIZE=true</classname> als Option zum
- Adapter übergeben wird.
- </para>
- <example
- id="zend.db.adapter.connecting.getconnection.example">
- <title>Umgang mit Verbindungs Exceptions</title>
- <programlisting language="php"><![CDATA[
- try {
- $db = Zend_Db::factory('Pdo_Mysql', $parameters);
- $db->getConnection();
- } catch (Zend_Db_Adapter_Exception $e) {
- // Möglicherweise ein fehlgeschlagener login,
- // oder die RDBMS läuft möglicherweise nicht
- } catch (Zend_Exception $e) {
- // Möglicherweise kann factory() die definierte Adapter Klasse nicht laden
- }
- ]]></programlisting>
- </example>
- </sect3>
- </sect2>
- <sect2 id="zend.db.adapter.example-database">
- <title>Beispiel Datenbank</title>
- <para>
- In der Dokumentation für die <classname>Zend_Db</classname> Klassen verwenden wir einige
- einfache Tabellen um die Verwendung der Klassen und Methoden zu erläutern. Diese
- Beispieltabellen können Informationen für das Bugtracking in einem Softwareprojekt
- speichern. Die Datenbank enthält vier Tabellen:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>accounts</emphasis> speichert Informationen über jeden Benutzer des
- Bugtracking Systems.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>products</emphasis> speichert Informationen über jedes Produkt für das
- ein Bug erfasst werden kann.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>bugs</emphasis> speichert informationen über Bugs, dazu gehört der
- derzeitige Status des Bugs, die Person die den Bug berichtet hat, die Person die
- den Bug beheben soll und die Person die die Fehlerbehebung verifizieren soll.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>bugs_products</emphasis> speichert Beziehungen zwischen Bugs und
- Produkten. Dies enthält eine Viele-zu-Viele Beziehung, da ein Bug für mehrere
- Produkte relevant sein kann. Und natürlich kann ein Produkt auch mehrere Bugs
- enthalten.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- Der folgende SQL Daten Definitions Sprache Pseudocode beschreibt die Tabellen in dieser
- Beispieldatenbank. Diese Beispieltabellen werden intensiv bei den automatisierten
- Unit-Tests für <classname>Zend_Db</classname> verwendet.
- </para>
- <programlisting language="sql"><![CDATA[
- CREATE TABLE accounts (
- account_name VARCHAR(100) NOT NULL PRIMARY KEY
- );
- CREATE TABLE products (
- product_id INTEGER NOT NULL PRIMARY KEY,
- product_name VARCHAR(100)
- );
- CREATE TABLE bugs (
- bug_id INTEGER NOT NULL PRIMARY KEY,
- bug_description VARCHAR(100),
- bug_status VARCHAR(20),
- reported_by VARCHAR(100) REFERENCES accounts(account_name),
- assigned_to VARCHAR(100) REFERENCES accounts(account_name),
- verified_by VARCHAR(100) REFERENCES accounts(account_name)
- );
- CREATE TABLE bugs_products (
- bug_id INTEGER NOT NULL REFERENCES bugs,
- product_id INTEGER NOT NULL REFERENCES products,
- PRIMARY KEY (bug_id, product_id)
- );
- ]]></programlisting>
- <para>
- Weiterhin zu beachten ist, dass die <code>bugs</code> Tabelle mehrere Foreign-Key
- References zu der <code>accounts</code> Tabelle enthält. Jeder dieser Foreign-Keys kann
- auf eine andere Zeile für einen angegebenen Bug in der <code>accounts</code> Tabelle
- verweisen.
- </para>
- <para>
- Das unten stehende Diagramm illustriert das physische Datenmodell der Beispieldatenbank.
- </para>
- <para>
- <inlinegraphic width="387" scale="100" align="center" valign="middle"
- fileref="figures/zend.db.adapter.example-database.png" format="PNG" />
- </para>
- </sect2>
- <sect2 id="zend.db.adapter.select">
- <title>Lesen von Abfrageergebnissen</title>
- <para>
- Dieser Abschnitt beschreibt Methoden der Adapterklasse mit denen SELECT Abfragen
- ausgeführt werden können um Abfrageergebnisse abzurufen.
- </para>
- <sect3 id="zend.db.adapter.select.fetchall">
- <title>Holen des kompletten Ergebnisssatzes</title>
- <para>
- Man kann eine SQL SELECT Anfrage ausführen und alle Ergebnisse auf einmal mit der
- <code>fetchAll()</code> Methode abrufen.
- </para>
- <para>
- Das erste Argument dieser Methode ist ein String der die SELECT Anweisung enthält.
- Als Alternative kann das erste Argument auch ein Objekt der
- <link linkend="zend.db.select">Zend_Db_Select</link> Klasse sein. Der Adapter
- konvertiert dieses automatisch in einen String der die SELECT Anweisung
- repräsentiert.
- </para>
- <para>
- Das zweite Argument von <code>fetchAll()</code> ist ein Array von Werten die
- Parameterplatzhalter in der SQL Anweisung ersetzen.
- </para>
- <example id="zend.db.adapter.select.fetchall.example">
- <title>Nutzung von fetchAll()</title>
- <programlisting language="php"><![CDATA[
- $sql = 'SELECT * FROM bugs WHERE bug_id = ?';
- $result = $db->fetchAll($sql, 2);
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.select.fetch-mode">
- <title>Ändern des Fetch Modus</title>
- <para>
- Standardmäßig gibt <code>fetchAll()</code> ein Array von Zeilen, jede als
- assoziatives Array, zurück. Die Schlüssel von diesem assoziativem Array entsprechen
- den Spalten oder Spaltenaliasen wie sie in der SELECT Anfrage benannt sind.
- </para>
- <para>
- Man kann einen anderen Stil für das Holen der Ergebnisse mit der
- <code>setFetchMode()</code> Methode angeben. Die unterstützten Modi werden mit
- folgenden Konstanten identifiziert:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>Zend_Db::FETCH_ASSOC</emphasis>:
- Gibt Daten in einem assoziativem Array zurück. Die Array Schlüssel sind
- Strings der Spaltennamen. Dies ist der Standardmodus für
- <classname>Zend_Db_Adapter</classname> Klassen.
- </para>
- <para>
- Zu beachten ist, dass wenn die Select-Liste mehr als eine Spalte mit dem
- selben Namen enthält, zum Beispiel wenn diese aus verschiedenen Tabellen
- durch einem JOIN bestehen, kann nur einer der Einträge in dem assoziativem
- Array enthalten sein. Wenn der FETCH_ASSOC Modus verwandt wird, sollten
- Spaltenaliase in der SELECT Anfrage angegeben werden um sicherzustellen das
- die Namen eindeutige Arrayschlüssel ergeben.
- </para>
- <para>
- Standardmäßig werden die Strings so zurück gegeben wie sie von dem
- Datenbanktreiber geliefert werden. Dies entspricht der typischen
- Schreibweise der Spaltennamen auf dem RDBMS Server. Die Schreibweise dieser
- Strings kann mit der <classname>Zend_Db::CASE_FOLDING</classname> Option
- angegeben werden. Dies muss bei der Instanziierung des Adapters angegeben
- werden. Beschreibung unter
- <xref linkend="zend.db.adapter.connecting.parameters.example1" />.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>Zend_Db::FETCH_NUM</emphasis>: Gibt Daten in einem Array von
- Arrays zurück. Die Arrays werden über Integer indiziert, entsprechend der
- Position der betreffenden Felder in der Select-Liste der Anfrage.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>Zend_Db::FETCH_BOTH</emphasis>: Gibt ein Array von Arrays zurück.
- Die Arrayschlüssel sind sowohl Strings wie beim FETCH_ASSOC Modus, als auch
- Integer wie beim FETCH_NUM modus. Zu beachten ist, dass die Anzahl der
- Elemente in dem Array doppelt so groß ist, als wenn FETCH_ASSOC oder
- FETCH_NUM verwendet worden wäre.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>Zend_Db::FETCH_COLUMN</emphasis>: Gibt Daten in einem Array von
- Werten zurück. Die Werte in jedem Array sind die Werte wie sie in einer
- Spalte des Ergebnisses zurück gegeben wurden. Standardmäßig ist die erste
- Spalte mit 0 indiziert.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>Zend_Db::FETCH_OBJ</emphasis>: Gibt Daten in einem Array von
- Objekten zurück. Die Standardklasse ist die in PHP eingebaute Klasse
- stdClass. Spalten des Ergebnisses sind als öffentliche Eigenschaften des
- Objekts verfügbar.
- </para>
- </listitem>
- </itemizedlist>
- <example id="zend.db.adapter.select.fetch-mode.example">
- <title>Nutzung von setFetchMode()</title>
- <programlisting language="php"><![CDATA[
- $db->setFetchMode(Zend_Db::FETCH_OBJ);
- $result = $db->fetchAll('SELECT * FROM bugs WHERE bug_id = ?', 2);
- // $result ist ein Array von Objekten
- echo $result[0]->bug_description;
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.select.fetchassoc">
- <title>Holen eines Ergbnisssatzes als assoziatives Array</title>
- <para>
- Die <code>fetchAssoc()</code> Methode gibt Daten in einem Array von assoziativen
- Array zurück, egal welcher Wert für den fetch-Modus gesetzt wurde.
- </para>
- <example id="zend.db.adapter.select.fetchassoc.example">
- <title>Nutzung von fetchAssoc()</title>
- <programlisting language="php"><![CDATA[
- $db->setFetchMode(Zend_Db::FETCH_OBJ);
- $result = $db->fetchAssoc('SELECT * FROM bugs WHERE bug_id = ?', 2);
- // $result ist ein Array von assoziativen Arrays im Geist von fetch mode
- echo $result[0]['bug_description'];
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.select.fetchcol">
- <title>Holen einer einzelnen Spalte eines Ergebnisssatzes</title>
- <para>
- Die <code>fetchCol()</code> Methode gibt Daten in einem Array von Werten zurück,
- egal welcher Wert für den fetch-Modus gesetzt wurde. Sie gibt nur die erste Spalte
- der Anfrage zurück. Alle weiteren Spalten der Anfrage werden verworfen. Wenn eine
- andere Spalte als die Erste benötigt wird sollte
- <xref linkend="zend.db.statement.fetching.fetchcolumn" /> beachtet werden.
- </para>
- <example id="zend.db.adapter.select.fetchcol.example">
- <title>Nutzung von fetchCol()</title>
- <programlisting language="php"><![CDATA[
- $db->setFetchMode(Zend_Db::FETCH_OBJ);
- $result = $db->fetchCol(
- 'SELECT bug_description, bug_id FROM bugs WHERE bug_id = ?', 2);
- // Enthält bug_description; bug_id wird nicht zurückgegeben
- echo $result[0];
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.select.fetchpairs">
- <title>Holen von Schlüssel-Wert Paaren eines Ergebnisssatzes</title>
- <para>
- Die <code>fetchPairs()</code> Methode gibt Daten in einem Array von Schlüssel-Wert
- Paaren zurück, einem assoziativen Array mit einem einzelnen Eintrag pro Zeile. Der
- Schlüssel dieses assoziativen Arrays wird von der ersten Spalte des SELECT
- Ergebnisses genommen. Der Wert wird aus der zweiten Spalte des SELECT Ergebnisses
- genommen. Alle weiteren Spalten des Ergebnisses werden verworfen.
- </para>
- <para>
- Die SELECT Anfrage sollte so gestaltet sein, dass die erste Spalte nur eindeutige
- Werte liefert. Wenn doppelte Werte in der ersten Spalte vorkommen, werden
- entsprechende Einträge in dem assoziativen Array überschrieben.
- </para>
- <example id="zend.db.adapter.select.fetchpairs.example">
- <title>Nutzung von fetchPairs()</title>
- <programlisting language="php"><![CDATA[
- $db->setFetchMode(Zend_Db::FETCH_OBJ);
- $result = $db->fetchAssoc('SELECT bug_id, bug_status FROM bugs');
- echo $result[2];
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.select.fetchrow">
- <title>Holen einer einzelnen Zeile eines Ergebnisssatzes</title>
- <para>
- Die <code>fetchRow()</code> Methode gibt Daten entsprechend dem fetch-Modus zurück,
- jedoch nur die erste Zeile des Ergebnisssatzes.
- </para>
- <example id="zend.db.adapter.select.fetchrow.example">
- <title>Nutzung von fetchRow()</title>
- <programlisting language="php"><![CDATA[
- $db->setFetchMode(Zend_Db::FETCH_OBJ);
- $result = $db->fetchRow('SELECT * FROM bugs WHERE bug_id = 2');
- // Beachte das $result ein einzelnes Objekt ist, und kein Array von Objekten
- echo $result->bug_description;
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.select.fetchone">
- <title>Holen eines einzelnen Scalars aus einem Ergebnisssatz</title>
- <para>
- Die <code>fetchOne()</code> Methode ist wie eine Kombination von
- <code>fetchRow()</code> mit <code>fetchCol()</code>, gibt also nur die erste Zeile
- des Ergebnisssatze zurück, und von dieser auch nur den Wert der ersten Spalte. Daher
- wird nur ein einziger scalarer Wert zurückgegeben, kein Array und auch kein Objekt.
- </para>
- <example id="zend.db.adapter.select.fetchone.example">
- <title>Nutzung von fetchOne()</title>
- <programlisting language="php"><![CDATA[
- $result = $db->fetchOne('SELECT bug_status FROM bugs WHERE bug_id = 2');
- // this is a single string value
- echo $result;
- ]]></programlisting>
- </example>
- </sect3>
- </sect2>
- <sect2 id="zend.db.adapter.write">
- <title>Schreiben von Änderungen in die Datenbank</title>
- <para>
- Die Adapterklasse kann verwendet werden um neue Daten in die Datenbank zu schreiben oder
- bestehende Daten in der Datenbank zu ändern. Dieser Abschnitt beschreibt Methoden für
- diese Operationen.
- </para>
- <sect3 id="zend.db.adapter.write.insert">
- <title>Einfügen von Daten</title>
- <para>
- Neue Zeilen können in die Datenbank mit der <code>insert()</code> Methode eingefügt
- werden. Das erste Argument ist ein String der die Tabelle benennt, und das zweite
- Argument ist ein assoziatives Array das den Spaltennamen Datenwerte zuordnet.
- </para>
- <example id="zend.db.adapter.write.insert.example">
- <title>Einfügen in eine Tabelle</title>
- <programlisting language="php"><![CDATA[
- $data = array(
- 'created_on' => '2007-03-22',
- 'bug_description' => 'Etwas falsch',
- 'bug_status' => 'NEW'
- );
- $db->insert('bugs', $data);
- ]]></programlisting>
- </example>
- <para>
- Spalten die nicht in dem Array definiert sind, werden nicht an die Datenbank
- übergeben. Daher folgen sie den selben Regeln denen eine SQL INSERT Anweisung folgt:
- wenn die Spalte einen Standardwert hat, so bekommt die Spalte der neuen Zeile diesen
- Wert. Andernfalls behält sie den Status <constant>NULL</constant>.
- </para>
- <para>
- Standardmäßig werden die Daten in dem Array mit Parametern eingefügt. Dies reduziert
- das Risiko einiger Typen von Sicherheitsproblemen. Die Werte in dem Array müssen
- daher nicht escaped oder quotiert übergeben werden.
- </para>
- <para>
- Einige Werte in dem Array könnten als SQL Expressions benötigt werden, in diesem
- Fall dürfen sie nicht in Anführungszeichen stehen. Standardmäßig werden alle
- übergebenen String-Werte als String-literale behandelt. Um anzugeben das ein Wert
- eine SQL Expression ist, und daher nicht quotiert werden soll, muss der Wert als ein
- Objekt des Typs <classname>Zend_Db_Expr</classname> übergeben werden, und nicht als
- einfacher String.
- </para>
- <example id="zend.db.adapter.write.insert.example2">
- <title>Einfügen von Expressions in eine Tabelle</title>
- <programlisting language="php"><![CDATA[
- $data = array(
- 'created_on' => new Zend_Db_Expr('CURDATE()'),
- 'bug_description' => 'Etwas falsch',
- 'bug_status' => 'NEW'
- );
- $db->insert('bugs', $data);
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.write.lastinsertid">
- <title>Abfragen von generierten Werten</title>
- <para>
- Einige RDBMS Marken unterstützen Auto-Incrementierung von Primärschlüsseln. Eine
- Tabelle die so definiert ist generiert automatisch einen Primärschlüsselwert während
- des INSERTs einer neuen Zeile. Der Rückgabewert der <code>insert()</code> Methode
- ist <emphasis>nicht</emphasis> die letzte eingefügte ID, weil die Tabelle keine
- Auto-Increment Spalte haben könnte. Statt dessen ist der Rückgabewert die Anzahl der
- betroffenen Zeilen (normalerweise 1).
- </para>
- <para>
- Wenn die Tabelle mit einem Auto-Increment Primärschlüssel definiert ist, kann die
- <code>lastInsertId()</code> Methode nach dem INSERT aufgerufen werden. Diese Methode
- gibt den letzten generierten Wertim Rahmen der aktuellen Datenbankverbindung zurück.
- </para>
- <example id="zend.db.adapter.write.lastinsertid.example-1">
- <title>Nutzung von lastInsertId() für einen Auto-Increment Schlüssel</title>
- <programlisting language="php"><![CDATA[
- $db->insert('bugs', $data);
- // Gib den letzten durch eine auto-inkrement Spalte erzeugten Wert zurück
- $id = $db->lastInsertId();
- ]]></programlisting>
- </example>
- <para>
- Einige RDBMS Marken unterstützen ein Sequenz-Objekt, welches eindeutige Werte
- generiert, die als Primärschlüsselwerte dienen. Um Sequenzen zu unterstützen,
- akzeptiert die <code>lastInsertId()</code> Method zwei optionale String Argumente.
- Diese Argumente benennen die Tabelle und die Spalte, in der Annahme das die
- Konvention beachtet wurde, dass eine Sequenz mit der Tabelle und der Spalte benannt
- wurde, für die sie Werte generiert plus dem Anhang "_seq". Dies basiert auf der
- Konvention die von PostgreSQL verwendet wird, wenn Sequenzen für SERIAL Spalten
- benannt werden. Zum Beispiel würde eine Tabelle "bugs" mit der Primärschlüsselspalte
- "bug_id" eine Sequenz als "bugs_bug_id_seq" benennen.
- </para>
- <example id="zend.db.adapter.write.lastinsertid.example-2">
- <title>Nutzung von lastInsertId() für eine Sequenz</title>
- <programlisting language="php"><![CDATA[
- $db->insert('bugs', $data);
- // Gib den letzten durch die 'bugs_bug_id_seq' Sequenz erstellten Wert zurück
- $id = $db->lastInsertId('bugs', 'bug_id');
- // Gib, alternativ, den letzten durch die 'bugs_seq' Sequenz
- // erstellten Wert zurück
- $id = $db->lastInsertId('bugs');
- ]]></programlisting>
- </example>
- <para>
- Wenn der Name des Squenz-Objekts nicht dieser Konvention folgt muss die
- <code>lastSequenceId()</code> Methode an Stelle verwendet werden. Diese Methode
- benötigt ein String Argument, welches die Sequenz wörtlich benennt.
- </para>
- <example id="zend.db.adapter.write.lastinsertid.example-3">
- <title>Nutzung von lastSequenceId()</title>
- <programlisting language="php"><![CDATA[
- $db->insert('bugs', $data);
- // Gib den letzten durch die 'bugs_id_gen' Sequenz erstellten Wert zurück.
- $id = $db->lastSequenceId('bugs_id_gen');
- ]]></programlisting>
- </example>
- <para>
- Bei RDBMS Marken die keine Sequenzen unterstützen, dazu gehören MySQL, Microsoft SQL
- Server und SQLite, werden die Argumente an die <code>lastInsertId()</code> Methode
- ignoriert, und der zurück gegebene Wert ist der zuletzt für eirgendeine Tabelle
- während einer INSERT Operation generierte Wert innerhalb der aktuellen Verbindung.
- Für diese RDBMS Marken gibt die <code>lastSequenceId()</code> Methode immer
- <constant>NULL</constant> zurück.
- </para>
- <note>
- <title>Weßhalb sollte man nicht "SELECT MAX(id) FROM table" verwenden?</title>
- <para>
- Manchmal gibt diese Anfrage den zuletzt eingefügten Primärschlüsselwert zurück.
- Trotzdem ist diese Technik in einer Umgebung in der mehrere Clients Daten in die
- Datenbank einfügen nicht sicher. Es ist möglich, und daher vorherbestimmt
- eventuell aufzutreten, das ein anderer Client in dem Augenblick zwischen dem
- INSERT deiner Client Anwendung und deiner Anfrage für den MAX(id) Wert, eine
- andere Zeile einfügt. Somit identifiziert der zurück gegebene Wert nicht die von
- dir eingefügte Zeile, sondern die eines anderen Clients. Man kann nie wissen
- wann dies passiert.
- </para>
- <para>
- Das Nutzen eines starken Transaktions Isolationsmodus wie "repeatable read" kann
- das Risiko mindern, aber einige RDBMS Marken unterstützen nicht die Transaktions
- Isolation die hierfür benötigt wird, oder deine Applikation könnte einen
- schwächeren Transaktions Isolationsmodus nutzen.
- </para>
- <para>
- Darüberhinaus ist das Nutzen eins Ausdrucks wie "MAX(id)+1" um einen neuen Wert
- für den Primärschlüssel zu generiern nict sicher, weil zwei Clients diese
- Anfrage gleichzeitig ausführen könnten und damit beide den gleichen Wert für
- ihre nächste INSERT Operation bekommen würden.
- </para>
- <para>
- Alle RDBMS Marken bieten einen Mechanismus um eindeutige Werte zu generieren,
- und um den zuletzt generierten Wert zurück zu geben. Diese Machanismen
- funktionieren notwendigerweise außerhalb des Gültigkeitsbereichs einer
- Transaktions Isolation, es besteht daher nicht die Möglichkeit das zwei Clients
- den selben Wert generieren und es besteht nicht die Möglichkeit das der Wert,
- der von einem anderen Client generiert wurde, an die Verbindung deines Clients,
- als letzter generierter Wert, gesendet wird.
- </para>
- </note>
- </sect3>
- <sect3 id="zend.db.adapter.write.update">
- <title>Aktualisieren von Daten</title>
- <para>
- Zeilen in der Datenbank können mit der <code>update()</code> Methode eines Adapters
- aktualisiert werden. Diese Methode benötigt drei Argumente: Das Erste ist der Name
- der Tabelle und das Zweite ist ein assoziatives Array das den zu Ändernden Spalten
- neue Werte zuordnet.
- </para>
- <para>
- Die Werte des Datenarrays werden als String Literale behandelt. Beachte
- <xref linkend="zend.db.adapter.write.insert" /> für Informationen zur Nutzung von
- SQL Expressions in dem Datenarray.
- </para>
- <para>
- Das dritte Argument ist ein String der aus einer SQL Expression besteht, die genutzt
- wird um Kriterien für die Auswahl der zu ändernden Zeilen zu bestimmen. Die Werte
- und Bezeichner in diesem Argument werden nicht escaped oder quotiert. An dieser
- Stelle muss darauf geachtet werden das sichergestellt ist, das dynamischer Inhalt
- sicher in diesen String eingefügt wird. Unter
- <xref linkend="zend.db.adapter.quoting" /> sind Methoden beschrieben die dabei
- helfen können.
- </para>
- <para>
- Der Rückgabewert ist die Anzahl der Betroffenen Zeilen der UPDATE Operation.
- </para>
- <example id="zend.db.adapter.write.update.example">
- <title>Aktualisieren von Zeilen</title>
- <programlisting language="php"><![CDATA[
- $data = array(
- 'updated_on' => '2007-03-23',
- 'bug_status' => 'FIXED'
- );
- $n = $db->update('bugs', $data, 'bug_id = 2');
- ]]></programlisting>
- </example>
- <para>
- Wenn das dritte Argument ausgelassen wird, werden alle Zeilen der Tabelle mit den
- Werten des Datenarrays aktualisiert.
- </para>
- <para>
- Wenn ein Array mit Strings als drittes Argument übergeben wird, werden diese Strings
- als eine Expression von Ausdrücken, getrennt von AND Operatoren, zusammengefügt.
- </para>
- <example id="zend.db.adapter.write.update.example-array">
- <title>Aktualisieren von Zeilen unter Nutzung eines Arrays von Expressions</title>
- <programlisting language="php"><![CDATA[
- $data = array(
- 'updated_on' => '2007-03-23',
- 'bug_status' => 'FIXED'
- );
- $where[] = "reported_by = 'goofy'";
- $where[] = "bug_status = 'OPEN'";
- $n = $db->update('bugs', $data, $where);
- // Der erstellte SQL Syntax ist:
- // UPDATE "bugs" SET "update_on" = '2007-03-23', "bug_status" = 'FIXED'
- // WHERE ("reported_by" = 'goofy') AND ("bug_status" = 'OPEN')
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.write.delete">
- <title>Löschen von Daten</title>
- <para>
- Daten können aus einer Datenbanktabelle mit der <code>delete()</code> Methode
- gelöscht werden. Diese Methode benötigt zwei Argumente: Das erste ist ein String der
- die Tabelle benennt.
- </para>
- <para>
- Das zweite Argument ist ein String der aus einer SQL Expression besteht, welche
- Kriterien für die zu löschenden Zeilen enthält. Die Werte und Bezeichner in diesem
- Argument werden nicht escaped quotiert. An dieser Stelle muss darauf geachtet werden
- das sichergestellt ist, das dynamischer Inhalt sicher in diesen String eingefügt
- wird. Unter <xref linkend="zend.db.adapter.quoting" /> sind Methoden beschrieben die
- dabei helfen können.
- </para>
- <para>
- Der Rückgabewert ist die Anzahl der Betroffenen Zeilen der DELETE Operation.
- </para>
- <example id="zend.db.adapter.write.delete.example">
- <title>Löschen von Zeilen</title>
- <programlisting language="php"><![CDATA[
- $n = $db->delete('bugs', 'bug_id = 3');
- ]]></programlisting>
- </example>
- <para>
- Wenn das zweite Argument ausgelassen wird, werden alle Zeilen der Tabelle gelöscht.
- </para>
- <para>
- Wenn ein Array mit Strings als zweites Argument übergeben wird, werden diese Strings
- als eine Expression von Ausdrücken, getrennt von AND Operatoren, zusammengefügt.
- </para>
- </sect3>
- </sect2>
- <sect2 id="zend.db.adapter.quoting">
- <title>Quotierung von Werten und Bezeichnern</title>
- <para>
- Beim Erzeugen von SQL Anfragen ist es häufig nötig PHP Variablen in die SQL Expression
- einzufügen. Dies ist riskant, weil der Wert eines PHP Strings bestimmte Zeichen
- enthalten kann, wie das Anführungszeichen, was zu ungültiger SQL Syntax führen kann. Zum
- Beispiel, zu beachten ist die ungerade Anzahl der Anführungszeichen in der folgenden
- Anfrage:
- <programlisting language="php"><![CDATA[
- $name = "O'Reilly";
- $sql = "SELECT * FROM bugs WHERE reported_by = '$name'";
- echo $sql;
- // SELECT * FROM bugs WHERE reported_by = 'O'Reilly'
- ]]></programlisting>
- </para>
- <para>
- Noch schlimmer ist das Risiko, dass solche Code-Fehler von einer Person absichtlich
- ausgenutzt werden um die Funktion der Webanwendung zu manipulieren. Wenn der Wert einer
- PHP Variablen über die Nutzung von HTTP Parametern oder eines anderen Mechanismus
- gesetzt werden kann, könnte eine Person die SQL Anfragen nutzen um Dinge zu tun, wozu
- sie nicht gedacht sind, wie Daten ausgeben, wozu die Person keine Zugangsberechtigung
- hat. Dies ist eine ernst zu nehmende und weit verbreitete Technik um die Sicherheit
- einer Anwendung zu verletzen, bekannt unter dem Namen "SQL Injection" (siehe
- <ulink url="http://en.wikipedia.org/wiki/SQL_Injection">http://en.wikipedia.org/wiki/SQL_Injection</ulink>).
- </para>
- <para>
- Die <classname>Zend_Db</classname> Adapterklassen bieten bequeme Methoden, die helfen
- die Verletzbarkeit durch SQL Injection Angriffe im PHP Code zu reduzieren. Die Lösung
- ist bestimmte Zeichen, wie Anführungszeichen, in PHP Werten zu ersetzen bevor sie in SQL
- Strings eingefügt werden. Dies schützt sowohl vor versehentlicher als auch vor
- absichtlicher Manipulation von SQL Strings durch PHP Variablen, die spezielle Zeichen
- enthalten.
- </para>
- <sect3 id="zend.db.adapter.quoting.quote">
- <title>Nutzung von quote()</title>
- <para>
- Die <code>quote()</code> Methode benötigt ein Argument, einen scalaren String Wert.
- Sie gibt den Wert mit ersetzten speziellen Zeichen, passend zu dem eingesetzten
- RDBMS, und umgeben von Stringwertbegrenzern zurück. Der Standard SQL
- Stringwertbegrenzer ist das einfache Anführungszeichen (<code>'</code>).
- </para>
- <example id="zend.db.adapter.quoting.quote.example">
- <title>Nutzung von quote()</title>
- <programlisting language="php"><![CDATA[
- $name = $db->quote("O'Reilly");
- echo $name;
- // 'O\'Reilly'
- $sql = "SELECT * FROM bugs WHERE reported_by = $name";
- echo $sql;
- // SELECT * FROM bugs WHERE reported_by = 'O\'Reilly'
- ]]></programlisting>
- </example>
- <para>
- Zu beachten ist, dass der Rückgabewert von <code>quote()</code> die
- Stringwertbegrenzer enthält. Dies ist ein Unterschied zu anderen Methoden die
- spezielle Zeichen ersetzen, aber keine Stringwertbegrenzer hinzufügen, wie z.B.
- <ulink url="http://www.php.net/mysqli_real_escape_string">mysql_real_escape_string()</ulink>.
- </para>
- <para>
- Es kann notwendig sein Werte in Anführungszeichen zu setzen oder nicht je nach dem
- Kontext des SQL Datentyps in dem diese verwendet werden. Zum Beispiel darf, in
- einigen RDBMS Typen, ein Integer Wert nicht wie in String in Anführungszeichen
- gesetzt werden, wenn dieser mit einer Integer-Typ Spalte oder einem Ausdruck
- verglichen wird. Anders gesagt ist das folgende in einigen SQL Implementationen ein
- Fehler, wenn angenommen wird das <code>intColumn</code> einen SQL Datentyp von
- <code>INTEGER</code> besitzt
- <programlisting language="php"><![CDATA[
- SELECT * FROM atable WHERE intColumn = '123'
- ]]></programlisting>
- </para>
- <para>
- Es kann das optionale zweite Argument der <code>quote()</code> Methode verwendet
- werden um die Verwendung von Anführungszeichen selektiv für den spezifizierten SQL
- Datentyp auszuwählen.
- </para>
- <example id="zend.db.adapter.quoting.quote.example-2">
- <title>Verwenden von quote() mit einem SQL Typ</title>
- <programlisting language="php"><![CDATA[
- $value = '1234';
- $sql = 'SELECT * FROM atable WHERE intColumn = '
- . $db->quote($value, 'INTEGER');
- ]]></programlisting>
- </example>
- <para>
- Jede <classname>Zend_Db_Adapter</classname> Klasse hat den Namen des nummerischen
- SQL Datentyps für die respektive Marke von RDBMS codiert. Man kann genauso die
- Konstanten <classname>Zend_Db::INT_TYPE</classname>,
- <classname>Zend_Db::BIGINT_TYPE</classname>, und
- <classname>Zend_Db::FLOAT_TYPE</classname> verwenden um Code in einem mehr
- RDBMS-unabhängigen Weg zu schreiben.
- </para>
- <para>
- <classname>Zend_Db_Table</classname> definiert SQL Typen zu <code>quote()</code>
- automatisch wenn SQL Abfragen erstellt werden die einer Tabellen Schlüssel Spalte
- entsprechen.
- </para>
- </sect3>
- <sect3 id="zend.db.adapter.quoting.quote-into">
- <title>Nutzung von quoteInto()</title>
- <para>
- Die typischste Anwendung von Quotierung ist das Einfügen von PHP Variablen in eine
- SQL Expression oder Anweisung. Die <code>quoteInto()</code> Methode kann verwendet
- werden um dies in einem Schritt zu erledigen. Die Methode benötigt zwei Argumente:
- Das erste Argument ist ein String der ein Platzhaltersymbol (<code>?</code>)
- enthält, und das zweite Argument ist ein Wert oder eine PHP Variable die den
- Platzhalter ersetzen soll.
- </para>
- <para>
- Das Platzhaltersymbol ist das gleiche Symbol wie es von vielen RDBMS Marken für Lage
- betreffende Parameter verwendet wird, aber die <code>quoteInto()</code> Methode
- bildet nur Abfrageparameter nach. Die Methode fügt den Wert des Strings in den SQL
- String ein, ersetzt dabei spezielle Zeichen und fügt Stringwertbegrenzer ein. Echte
- Abfrageparameter sorgen für eine Trennung von SQL String und Parametern wenn die
- Anweisung vom RDBMS Server verarbeitet wird.
- </para>
- <example id="zend.db.adapter.quoting.quote-into.example">
- <title>Nutzung von quoteInto()</title>
- <programlisting language="php"><![CDATA[
- $sql = $db->quoteInto("SELECT * FROM bugs WHERE reported_by = ?", "O'Reilly");
- echo $sql;
- // SELECT * FROM bugs WHERE reported_by = 'O\'Reilly'
- ]]></programlisting>
- </example>
- <para>
- Man kann den optionalen dritten Parameter von <code>quoteInto()</code> verwenden um
- den SQL Datentyp zu spezifizieren. Nummerische Datentypen werden nicht in
- Anführungszeichen gesetzt und andere Typen werden in Anführungszeichen gesetzt.
- </para>
- <example id="zend.db.adapter.quoting.quote-into.example-2">
- <title>Verwenden von quoteInto() mit einem SQL Typ</title>
- <programlisting language="php"><![CDATA[
- $sql = $db
- ->quoteInto("SELECT * FROM bugs WHERE bug_id = ?", '1234', 'INTEGER');
- echo $sql;
- // SELECT * FROM bugs WHERE reported_by = 1234
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.adapter.quoting.quote-identifier">
- <title>Nutzung von quoteIdentifier()</title>
- <para>
- Werte könnten nicht der einzige Teil der SQL Syntax sein, der Variabel sein soll.
- Wenn PHP Variablen genutzt werden um Tabellen, Spalten oder andere Bezeichner in den
- SQL Anweisungen zu benennen, könnte es nötig sein das diese Strings ebenfalls
- quotiert werden müssen. Standardmäßig haben SQL Bezeichner Syntaxregeln wie PHP und
- die meißten anderen Programmiersprachen. Zum Beispiel dürfen Bezeichner keine
- Leerzeichen, bestimmte Punktierung, spezielle Zeichen oder Internationale Zeichen
- enthalten. Außerdem sind bestimmte Wörter für die SQL Syntax reserviert und dürfen
- nicht als Bezeichner verwendet werden.
- </para>
- <para>
- Dennoch hat SQL ein Feature mit Namen
- <emphasis>delimited identifiers (begrenzte Bezeichner)</emphasis>, welches eine
- größere Auswahl bei der Schreibweise von Bezeichnern erlaubt. Wenn ein SQL
- Bezeichner mit dem richtigen Typ von´ Quotierung eingeschlossen ist, können
- Schreibweisen für die Bezeichner verwendet werden, die ohne der Quotierung ungültig
- wären. Begrenzte Bezeichner können Leerzeichen, Punktierung oder internationale
- Zeichen enthalten. Desweiteren dürfen auch von der SQL Syntax reservierte Wörter
- verwendet werden, wenn sie von Bezeichner Begrenzungszeichen eingeschlossen sind.
- </para>
- <para>
- Die <code>quoteIdentifier()</code> Methode funktioniert wie <code>quote()</code>,
- aber sie wendet die Bezeichner Begrenzungszeichen entsprechend dem verwendeten
- Adapter an. Zum Beispiel nutzt Standard-SQL doppelte Anführungszeichen
- (<code>"</code>) zum begrenzen von Bezeichnern und die meisten der RDBMS Marken
- nutzen ebendfalls dieses Symbol. MySQL hingegen benutzt back-quotes (<code>`</code>)
- als Standardzeichen. Die <code>quoteIdentifier()</code> Methode ersetzt außerdem
- spezielle Zeichen im String Argument.
- </para>
- <example id="zend.db.adapter.quoting.quote-identifier.example">
- <title>Nutzung von quoteIdentifier()</title>
- <programlisting language="php"><![CDATA[
- // Wir könnten einen Tabellennamen haben, der ein in SQL reserviertes Wort ist
- $tableName = $db->quoteIdentifier("order");
- $sql = "SELECT * FROM $tableName";
- echo $sql
- // SELECT * FROM "order"
- ]]></programlisting>
- </example>
- <para>
- SQL begrenzte Bezeichner beachten die Groß- und Kleinschreibung, im Gegensatz zu
- nicht quotierten Bezeichnern. Daher muss, bei Verwendung von begrenztern
- Bezeichnern, die Schreibung der Bezeichner genau der Schreibung der Bezeichner im
- Tabellenschema entsprechen. Einschließlich der Groß- und Kleinschreibung.
- </para>
- <para>
- In den meisten Fällen wo SQL innerhalb der <classname>Zend_Db</classname> Klassen
- generiert wird, werden standardmäßig alle Bezeichner automatisch begrenzt. Dieses
- Verhalten kann mit der Option <classname>Zend_Db::AUTO_QUOTE_IDENTIFIERS</classname>
- geändert werden. Dies muss beim Instanziieren des Adapters wie in
- <xref linkend="zend.db.adapter.connecting.parameters.example2" /> angegeben werden.
- </para>
- </sect3>
- </sect2>
- <sect2 id="zend.db.adapter.transactions">
- <title>Kontrollieren von Datenbank Transaktionen</title>
- <para>
- Datenbanken definieren Transaktionen als logische Einheiten von Arbeit, die als einzelne
- Änderung übergeben oder rückgängig gemacht werden kann, selbst wenn sie auf
- verschiedenen Tabellen operiert. Alle Anfragen an einen Datenbank werden im Kontext
- einer Transaktion ausgeführt, selbst wenn der Datenbanktreiber sie implizit Verwaltet.
- Es wird <emphasis>auto-commit</emphasis> Modus genannt, wenn der Datenbanktreiber eine
- Transaktion für jede Anweisung erzeugt, und diese direkt nach dem Ausführen übergibt.
- Standardmäßig operieren alle <classname>Zend_Db</classname> Adapterklassen im
- auto-commit Modus.
- </para>
- <para>
- Alternativ kann der Begin und das Ergebnis einer Transaktion selbst spezifiziert werden,
- und damit kann kontrolliert werden wieviele SQL Anfragen in einer Gruppe enthalten sind,
- die entweder übergeben oder rückgängig gemacht wird, als eine einzelne Operation. Um
- eine Transaktion zu initiieren wird die <code>beginTransaction()</code> Methode
- verwendet. Anschließend folgende SQL Anweisungen werden im Kontext der selben
- Transaktion ausgeführt bis sie explizit aufgelöst wird.
- </para>
- <para>
- Um eine Transaktion aufzulösen wird entweder die <code>commit()</code> oder die
- <code>rollBack()</code> Methode verwendet. Die <code>commit()</code> Methode markiert
- die Änderungen die während der Transaktionen durchgeführt wurden als übergeben, was
- bedeutet das die Effekte dieser Änderungen in anderen Transaktionen angezeigt werden.
- </para>
- <para>
- Die <code>rollBack()</code> Methode tut das Gegenteil: sie verwirft die Änderungen die
- während der Transaktionen durchgeführt wurden. Die Änderungen werden gewissermaßen
- ungeschehen gemacht, der Status der Daten ändert sich zurück auf jenen wie sie vor
- Beginn der Transaktion waren. Allerdings hat das rückgängig machen keinen Einfluss auf
- Änderungen die von anderen, gleichzeitig laufenden Transaktionen verursacht wurden.
- </para>
- <para>
- Nach dem Auflösen der Transaktion befindet sich der
- <classname>Zend_Db_Adapter</classname> wieder im auto-commit Modus, bis
- <code>beginTransaction()</code> wieder aufgerufen wird.
- </para>
- <example id="zend.db.adapter.transactions.example">
- <title>Verwalten einer Transaktion um Konsistenz sicher zu stellen</title>
- <programlisting language="php"><![CDATA[
- // Eine Transaktion explizit starten
- $db->beginTransaction();
- try {
- // Versuchen einen oder mehrere Abfragen auszuführen
- $db->query(...);
- $db->query(...);
- $db->query(...);
- // Wenn alle erfolgreich waren, übertrage die Transaktion
- // und alle Änderungen werden auf einmal übermittelt
- $db->commit();
- } catch (Exception $e) {
- // Wenn irgendeine der Abfragen fehlgeschlagen ist, wirf eine Ausnahme, wir
- // wollen die komplette Transaktion zurücknehmen, alle durch die
- // Transaktion gemachten Änderungen wieder entfernen, auch die erfolgreichen
- // So werden alle Änderungen auf einmal übermittelt oder keine
- $db->rollBack();
- echo $e->getMessage();
- }
- ]]></programlisting>
- </example>
- </sect2>
- <sect2 id="zend.db.adapter.list-describe">
- <title>Auflistung und Beschreibung von Tabellen</title>
- <para>
- Die <code>listTables()</code> Methode gibt ein Array von Strings zurück, mit den Namen
- aller Tabellen in der aktuellen Datenbank.
- </para>
- <para>
- Die <code>describeTable()</code> Methode gibt ein assoziatives Array von MetaDaten über
- die Tabelle zurück. Das erste Argument dieser Methode ist ein String der den Namen der
- Tabelle enthält. Das zweite Argument ist optional und benennt das Schema in dem die
- Tabelle besteht.
- </para>
- <para>
- Die Schlüssel des assoziativen Arrays sind die Spaltennamen der Tabelle. Der zugehörige
- Wert jeder Spalte ist ebenfalls ein assoziatives Array mit den folgenden Schlüsseln und
- Werten:
- </para>
- <table frame="all" cellpadding="5" id="zend.db.adapter.list-describe.metadata">
- <title>Metadata Felder die von describeTable() zurückgegeben werden</title>
- <tgroup cols="3" align="left" colsep="1" rowsep="1">
- <thead>
- <row>
- <entry>Schlüssel</entry>
- <entry>Typ</entry>
- <entry>Beschreibung</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>SCHEMA_NAME</entry>
- <entry>(string)</entry>
- <entry>Name des Datenbankschemas in welchem diese Tabelle existiert.</entry>
- </row>
- <row>
- <entry>TABLE_NAME</entry>
- <entry>(string)</entry>
- <entry>Name der Tabelle zu welcher diese Spalte gehört.</entry>
- </row>
- <row>
- <entry>COLUMN_NAME</entry>
- <entry>(string)</entry>
- <entry>Name der Spalte.</entry>
- </row>
- <row>
- <entry>COLUMN_POSITION</entry>
- <entry>(integer)</entry>
- <entry>Ordinale Position der Spalte in der Tabelle.</entry>
- </row>
- <row>
- <entry>DATA_TYPE</entry>
- <entry>(string)</entry>
- <entry>RDBMS Name des Datentyps der Spalte.</entry>
- </row>
- <row>
- <entry>DEFAULT</entry>
- <entry>(string)</entry>
- <entry>Standardwert der Spalte, wenn angegeben.</entry>
- </row>
- <row>
- <entry>NULLABLE</entry>
- <entry>(boolean)</entry>
- <entry>
- <constant>TRUE</constant> wenn die Spalte SQL NULL akzeptiert,
- <constant>FALSE</constant> wenn die Spalte eine NOT NULL Bedingung hat.
- </entry>
- </row>
- <row>
- <entry>LENGTH</entry>
- <entry>(integer)</entry>
- <entry>Länge oder Größe der Spalte wie vom RDBMS angegeben.</entry>
- </row>
- <row>
- <entry>SCALE</entry>
- <entry>(integer)</entry>
- <entry>Scalar vom Typ SQL NUMERIC oder DECIMAL.</entry>
- </row>
- <row>
- <entry>PRECISION</entry>
- <entry>(integer)</entry>
- <entry>Präzision des Typs SQL NUMERIC oder DECIMAL.</entry>
- </row>
- <row>
- <entry>UNSIGNED</entry>
- <entry>(boolean)</entry>
- <entry>
- <constant>TRUE</constant> wenn ein Integer-basierender Typ als UNSIGNED
- angegeben wird.
- </entry>
- </row>
- <row>
- <entry>PRIMARY</entry>
- <entry>(boolean)</entry>
- <entry>
- <constant>TRUE</constant> wenn die Spalte Teil des Primärschlüsssels der Tabelle
- ist.
- </entry>
- </row>
- <row>
- <entry>PRIMARY_POSITION</entry>
- <entry>(integer)</entry>
- <entry>
- Ordinale Position (1-basierend) der Spalte des Primärschlüssels.
- </entry>
- </row>
- <row>
- <entry>IDENTITY</entry>
- <entry>(boolean)</entry>
- <entry>
- <constant>TRUE</constant> wenn die Spalte einen auto-increment Wert nutzt.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <note>
- <title>Wie das IDENTITY Metadata Feld zu speziellen RDBMS zuzuordnen ist</title>
- <para>
- Das IDENTITY Metadata Feld wurd gewählt als ein 'idiomatischer' Ausdruck um eine
- Relation von Ersatzschlüsseln zu repräsentieren. Dieses Feld ist üblicherweise durch
- die folgenden Werte bekannt:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <code>IDENTITY</code> - DB2, MSSQL
- </para>
- </listitem>
- <listitem>
- <para>
- <code>AUTO_INCREMENT</code> - MySQL
- </para>
- </listitem>
- <listitem>
- <para>
- <code>SERIAL</code> - PostgreSQL
- </para>
- </listitem>
- <listitem>
- <para>
- <code>SEQUENCE</code> - Oracle
- </para>
- </listitem>
- </itemizedlist>
- </note>
- <para>
- Wenn keine Tabelle mit dem Tabellennamen und dem optional angegebenen Schemanamen
- existiert, gibt <code>describeTable()</code> ein leeres Array zurück.
- </para>
- </sect2>
- <sect2 id="zend.db.adapter.closing">
- <title>Schließen einer Verbindung</title>
- <para>
- Normalerweise ist es nicht nötig eine Datenbankverbindung zu schließen. PHP räumt
- automatisch alle Ressourcen am Ende einer Anfrage auf und die Datenbankerweiterungen
- sind so designed das sie Verbindungen beenden wenn Referenzen zu ihren Objekten
- aufgeräumt werden.
- </para>
- <para>
- Trotzdem könnte es sinnvoll sein, wenn ein lang andauerndes PHP Script verwendet wird,
- das viele Datenbankverbindungen hat, diese zu schließen um zu vermeiden das die
- Kapazität des RDBMS Servers überschritten wird. Die <code>closeConnection()</code>
- Methode der Adapterklasse kann verwendet werden um die zugrundeliegende
- Datenbankverbindung explizit zu schließen.
- </para>
- <para>
- Seit Release 1.7.2, kann man prüfen ob man mit der <code>isConnected()</code> prüfen ob
- man aktuell mit dem RDBMS Server verbunden ist. Das bedeutet das eine Verbindungs
- Ressource initialisiert und nicht geschlossen wurde. Diese Funktion ist aktuell nicht in
- der Lage zu prüfen ob zum Beispiel die Server Seite die Verbindung geschlossen hat. Das
- wird intern verwendet um die Verbindung zu schließen. Das erlaubt es die Verbindung ohne
- Fehler mehrere Male zu schließen. Das war bereits vor 1.7.2 der Fall für PDO Adapter,
- aber nicht für die anderen.
- </para>
- <example id="zend.db.adapter.closing.example">
- <title>Schließen einer Datenbankverbindung</title>
- <programlisting language="php"><![CDATA[
- $db->closeConnection();
- ]]></programlisting>
- </example>
- <note>
- <title>Unterstützt Zend_Db persistente Verbindungen?</title>
- <para>
- Die Nutzung von persistenten Verbindungen wird weder von
- <classname>Zend_Db</classname> unterstützt, noch gewünscht.
- </para>
- <para>
- Die Benutzung von persistenten Verbindungen kann überschüssige und untätige
- Verbindungen auf dem RDBMS Server verursachen, welche mehr Probleme bringen als
- Performancegewin, welcher möglicherweise angestrebt wird, durch das reduzieren des
- Overheads beim Starten von Verbindungen.
- </para>
- <para>
- Datenbankverbindungen haben einen Status. Natürlich existieren einige Objekte auf
- dem Server im Gültigkeitsbereich einer Session. Beispiele dafür sind locks, user
- variablen, temporary tables und Informationen über die zuletzt ausgeführte Anfrage,
- sowie betroffene Zeilen und zuletzt generierte ID Werte. Wenn persistente
- Verbindungen genutzt werden könnte die Anwendung Zugriff auf ungültige oder
- privilegierte Daten erlangen, die in einem vorigen PHP Request erzeugt wurden.
- </para>
- </note>
- </sect2>
- <sect2 id="zend.db.adapter.other-statements">
- <title>Ausführen anderer Datenbank Anweisungen</title>
- <para>
- Es könnte Fälle geben in denen direkter Zugriff auf das Verbindungsobjekt benötigt wird,
- wie es von der PHP Erweiterung bereitgestellt wird. Einige der Erweiterungen könnten
- Features anbieten, welche nicht von Methoden der
- <classname>Zend_Db_Adapter_Abstract</classname> Klasse auftauchen..
- </para>
- <para>
- Zum Beispiel werden alle SQL Anweisungen von <classname>Zend_Db</classname> vorbereitet
- und dann ausgeführt. Trotzdem gibt es einige Features welche nicht kompatibel mit
- vorbereiteten Anweisungen sind. DDL Anweisungen wie CREATE und ALTER können in MySQL
- nicht vorbereitet werden. Auch können SQL Anweisungen keinen Nutzen aus dem
- <ulink url="http://dev.mysql.com/doc/refman/5.1/en/query-cache-how.html">MySQL Query
- Cache</ulink> ziehen, bei einer geringeren MySQL Version als 5.1.17.
- </para>
- <para>
- Die meisten PHP Datenbankerweiterungen bieten eine Methode um SQL Anweisung auszuführen
- ohne diese vorzubereiten. Zum Beispiel bietet PDO die Methode <code>exec()</code>. Das
- Verbindungsobjekt der PHP Erweiterung kann kann mit der Methode
- <code>getConnection()</code> direkt verwendet werden.
- </para>
- <example id="zend.db.adapter.other-statements.example">
- <title>Ausführen eines nicht-prepared Statements mit einem PDO Adapter</title>
- <programlisting language="php"><![CDATA[
- $result = $db->getConnection()->exec('DROP TABLE bugs');
- ]]></programlisting>
- </example>
- <para>
- So ähnlich können auch andere Methoden oder Eigenschaften der speziellen PHP
- Datenbankerweiterung genutzt werden. Zu beachten dabei ist jedoch, dass dadurch
- möglicherweise die Anwendung auf das angegebene Interface, bereitgestellt von einer
- Erweiterung für ein bestimmtes RDBMS, beschränkt wird.
- </para>
- <para>
- In zukünftigen Versionen von <classname>Zend_Db</classname> werden Möglichkeiten gegeben
- sein, um Methoden Startpunkte hinzuzufügen, für Funktionalitäten die den unterstützten
- PHP Datenbankerweiterungen gemein sind. Dies wird die Rückwärtskompatibilität nicht
- beeinträchtigen.
- </para>
- </sect2>
- <sect2 id="zend.db.adapter.server-version">
- <title>Erhalten der Server Version</title>
- <para>
- Seit Release 1.7.2 kann man die Version des Servers in einem PHP artigen Stil erhalten
- damit man es mit <code>version_compare()</code> verwenden kann. Wenn die Information
- nicht vorhanden ist erhält man <constant>NULL</constant> zurück.
- </para>
- <example id="zend.db.adapter.server-version.example">
- <title>Prüfen der Server Version bevor eine Abfrage gestartet wird</title>
- <programlisting language="php"><![CDATA[
- $version = $db->getServerVersion();
- if (!is_null($version)) {
- if (version_compare($version, '5.0.0', '>=')) {
- // mach was
- } else {
- // mach was anderes
- }
- } else {
- // Server Version ist unmöglich zu lesen
- }
- ]]></programlisting>
- </example>
- </sect2>
- <sect2 id="zend.db.adapter.adapter-notes">
- <title>Anmerkungen zu bestimmten Adaptern</title>
- <para>
- Dieser Abschnitt beschreibt Unterschiede zwischen den verschieden Adapterklassen auf die
- man achtgeben sollte.
- </para>
- <sect3 id="zend.db.adapter.adapter-notes.ibm-db2">
- <title>IBM DB2</title>
- <itemizedlist>
- <listitem>
- <para>
- Dieser Adapter wird in der <code>factory()</code> Methode mit dem Namen
- 'Db2' angegeben.
- </para>
- </listitem>
- <listitem>
- <para>
- Dieser Adapter nutzt die PHP Erweiterung ibm_db2.
- </para>
- </listitem>
- <listitem>
- <para>
- IBM DB2 unterstützt sowohl Sequenzen als auch auto-increment Schlüssel.
- Daher sind die Argumente für <code>lastInsertId()</code> optional. Werden
- keine Argumente angegeben, gibt der Adapter den letzten Wert der für den
- auto-increment Key generiert wurde zurück. Werden Argumente angegeben, gibt
- der Adapter den letzten Wert der für die Sequenz mit dem Namen, entsprechend
- der Konvention, '<emphasis>table</emphasis>_<emphasis>column</emphasis>_seq'
- generiert wurde zurück.
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.adapter.adapter-notes.mysqli">
- <title>MySQLi</title>
- <itemizedlist>
- <listitem>
- <para>
- Dieser Adapter wird in der <code>factory()</code> Methode mit dem Namen
- 'Mysqli' angegeben.
- </para>
- </listitem>
- <listitem>
- <para>
- Dieser Adapter nutzt die PHP Erweiterung mysqli.
- </para>
- </listitem>
- <listitem>
- <para>
- MySQL unterstützt keine Sequenzen, daher ignoriert
- <code>lastInsertId()</code> Argumente und gibt immer den letzten Wert der
- für den auto-increment Schlüssel generiert wurde zurück. Die
- <code>lastSequenceId()</code> Methode gibt <constant>NULL</constant> zurück.
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.adapter.adapter-notes.oracle">
- <title>Oracle</title>
- <itemizedlist>
- <listitem>
- <para>
- Dieser Adapter wird in der <code>factory()</code> Methode mit dem Namen
- 'Oracle' angegeben.
- </para>
- </listitem>
- <listitem>
- <para>
- Dieser Adapter nutzt die PHP Erweiterung oci8.
- </para>
- </listitem>
- <listitem>
- <para>
- Oracle unterstützt keine auto-increment Schlüssel, daher sollte der Name
- einer Sequenz an <code>lastInsertId()</code> oder
- <code>lastSequenceId()</code> übergeben werden.
- </para>
- </listitem>
- <listitem>
- <para>
- Die Oracle Erweiterung unterstützt keine positionierten Parameter. Es müssen
- benannte Parameter verwendet werden.
- </para>
- </listitem>
- <listitem>
- <para>
- Aktuell wird die <classname>Zend_Db::CASE_FOLDING</classname> Option vom
- Oracle Adapter nicht unterstützt. Um diese Option mit Oracle zu nutzen muss
- der PDO OCI Adapter verwendet werden.
- </para>
- </listitem>
- <listitem>
- <para>
- Standardmäßig werden LOB Felder als OCI-Log Objekte zurückgegeben. Man kann
- Sie für alle Anfragen als String empfangen indem die Treiberoption
- <code>'lob_as_string'</code> verwendet wird, oder für spezielle Anfragen
- durch Verwendung von <code>setLobAsString(boolean)</code> auf dem Adapter
- oder dem Statement.
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.adapter.adapter-notes.pdo-mssql">
- <title>PDO Microsoft SQL Server</title>
- <itemizedlist>
- <listitem>
- <para>
- Dieser Adapter wird in der <code>factory()</code> Methode mit dem Namen
- 'Pdo_Mssql' angegeben.
- </para>
- </listitem>
- <listitem>
- <para>
- Dieser Adapter nutzt die PHP Erweiterungen pdo und pdo_mssql.
- </para>
- </listitem>
- <listitem>
- <para>
- Microsoft SQL Server unterstützt keine Sequenzen, daher ignoriert
- <code>lastInsertId()</code> Argumente und gibt immer den letzten Wert der
- für den auto-increment Schlüssel generiert wurde zurück. Die
- <code>lastSequenceId()</code> Methode gibt <constant>NULL</constant> zurück.
- </para>
- </listitem>
- <listitem>
- <para>
- Wenn man mit Unicode Strings in einer anderen Codierung als UCS-2 (wie
- UTF-8) arbeitet, kann es sein das man eine Konvertierung im eigenen
- Anwendungscode durchführen, oder die Daten in einer Binären Spalte speichern
- muß. Referieren Sie bitte auf
- <ulink url="http://support.microsoft.com/kb/232580">Microsoft's Knowledge
- Base</ulink> für weitere Informationen.
- </para>
- </listitem>
- <listitem>
- <para>
- <classname>Zend_Db_Adapter_Pdo_Mssql</classname> setzt
- <code>QUOTED_IDENTIFIER ON</code> direkt nach dem Verbinden zu einer SQL
- Server Datenbank. Dadurch verwendet der Treiber das Standard SQL Bezeichner
- Begrenzungssymbol (<code>"</code>) an Stelle der proprietären Eckige-Klammer
- Syntax die der SQL Server standradmäßig nutzt.
- </para>
- </listitem>
- <listitem>
- <para>
- Es kann <code>pdoType</code> als ein Schlüssel im Optionsarray gesetzt
- werden. Der Wert kann "mssql" (der Standard), "dblib", "freetds", oder
- "sybase" sein. Diese Option beeinflusst den DNS Prefix, welchen der Adapter
- beim Konstruieren des DNS Strings benutzt. Sowohl "freetds" als auch
- "sybase" implementieren einen Prefix von "sybase:", welcher für den
- <ulink url="http://www.freetds.org/">FreeTDS</ulink> Satz von Libraries
- verwendet wird. Siehe auch
- <ulink url="http://www.php.net/manual/de/ref.pdo-dblib.connection.php">http://www.php.net/manual/de/ref.pdo-dblib.connection.php</ulink>
- für weitere Informationen über die DNS Prefixe die von diesem Treiber
- verwendet werden.
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.adapter.adapter-notes.pdo-ibm">
- <title>PDO für IBM DB2 und Informix Dynamic Server (IDS)</title>
- <itemizedlist>
- <listitem>
- <para>
- Dieser Adapter wird in der <code>factory()</code> Methode mit dem Namen
- 'Pdo_Ibm' spezifiziert.
- </para>
- </listitem>
- <listitem>
- <para>
- Dieser Adapter nutzt die PHP Erweiterungen pdo und pdo_ibm.
- </para>
- </listitem>
- <listitem>
- <para>
- Es muß mindestens die PDO_IBM Erweiterung mit der Version 1.2.2 verwendet
- werden. Wenn eine ältere Version verwendet wird, muß die PDO_IBM Erweiterung
- über PECL hochgerüstet werden.
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.adapter.adapter-notes.pdo-mysql">
- <title>PDO MySQL</title>
- <itemizedlist>
- <listitem>
- <para>
- Dieser Adapter wird in der <code>factory()</code> Methode mit dem Namen
- 'Pdo_Mysql' angegeben.
- </para>
- </listitem>
- <listitem>
- <para>
- Dieser Adapter nutzt die PHP Erweiterungen pdo und pdo_mysql.
- </para>
- </listitem>
- <listitem>
- <para>
- MySQL unterstützt keine Sequenzen, daher ignoriert
- <code>lastInsertId()</code> Argumente und gibt immer den letzten Wert der
- für den auto-increment Schlüssel generiert wurde zurück. Die
- <code>lastSequenceId()</code> Methode gibt <constant>NULL</constant> zurück.
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.adapter.adapter-notes.pdo-oci">
- <title>PDO Oracle</title>
- <itemizedlist>
- <listitem>
- <para>
- Dieser Adapter wird in der <code>factory()</code> Methode mit dem Namen
- 'Pdo_Oci' angegeben.
- </para>
- </listitem>
- <listitem>
- <para>
- Dieser Adapter nutzt die PHP Erweiterungen pdo und pdo_oci.
- </para>
- </listitem>
- <listitem>
- <para>
- Oracle unterstützt keine auto-increment Schlüssel, daher sollte der Name
- einer Sequenz an <code>lastInsertId()</code> oder
- <code>lastSequenceId()</code> übergeben werden.
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.adapter.adapter-notes.pdo-pgsql">
- <title>PDO PostgreSQL</title>
- <itemizedlist>
- <listitem>
- <para>
- Dieser Adapter wird in der <code>factory()</code> Methode mit dem Namen
- 'Pdo_Pgsql' angegeben.
- </para>
- </listitem>
- <listitem>
- <para>
- Dieser Adapter nutzt die PHP Erweiterungen pdo und pdo_pgsql.
- </para>
- </listitem>
- <listitem>
- <para>
- PostgreSQL unterstützt sowohl Sequenzen als auch auto-increment Schlüssel.
- Daher sind die Argumente für <code>lastInsertId()</code> optional. Werden
- keine Argumente angegeben, gibt der Adapter den letzten Wert der für den
- auto-increment Key generiert wurde zurück. Werden Argumente angegeben, gibt
- der Adapter den letzten Wert der für die Sequenz mit dem Namen, entsprechend
- der Konvention, '<emphasis>table</emphasis>_<emphasis>column</emphasis>_seq'
- generiert wurde zurück.
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.adapter.adapter-notes.pdo-sqlite">
- <title>PDO SQLite</title>
- <itemizedlist>
- <listitem>
- <para>
- Dieser Adapter wird in der <code>factory()</code> Methode mit dem Namen
- 'Pdo_Sqlite' angegeben.
- </para>
- </listitem>
- <listitem>
- <para>
- Dieser Adapter nutzt die PHP Erweiterungen pdo und pdo_sqlite.
- </para>
- </listitem>
- <listitem>
- <para>
- SQLite unterstützt keine Sequenzen, daher ignoriert
- <code>lastInsertId()</code> Argumente und gibt immer den letzten Wert der
- für den auto-increment Schlüssel generiert wurde zurück. Die
- <code>lastSequenceId()</code> Methode gibt <constant>NULL</constant> zurück.
- </para>
- </listitem>
- <listitem>
- <para>
- Um mit einer SQLite2 Datenbank zu Verbinden muss
- <code>'sqlite2'=>true</code> in dem Array von Parametern beim Erzeugen einer
- Instanz des Pdo_Sqlite Adapters angegeben werden.
- </para>
- </listitem>
- <listitem>
- <para>
- Um mit einer in-memory SQLite Datenbank zu verbinden muss
- <code>'dbname'=>':memory:'</code> in dem Array von Parametern beim
- Erzeugen einer Instanz des Pdo_Sqlite Adapters angegeben werden.
- </para>
- </listitem>
- <listitem>
- <para>
- Ältere Versionen des SQLite Treibers in PHP scheinen die PRAGMA Kommandos
- nicht zu unterstützen, die benötigt werden um sicherzustellen, dass kurze
- Spaltennamen in Ergebnissätzen verwendet werden. Wenn in den Ergebnissätzen
- Schlüssel der Art "tabellenname.spaltenname" bei Nutzung von JOIN Abfragen
- auftreten, sollte die aktuellste PHP Version installiert werden.
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.adapter.adapter-notes.firebird">
- <title>Firebird/Interbase</title>
- <itemizedlist>
- <listitem>
- <para>
- Dieser Adapter verwendet die PHP Erweiterung php_interbase.
- </para>
- </listitem>
- <listitem>
- <para>
- Firebird/interbase unterstützt keine auto-increment Schlüssel, deswegen
- sollte der Name einer Sequenz bei <code>lastInsertId()</code> oder
- <code>lastSequenceId()</code> spezifiziert werden.
- </para>
- </listitem>
- <listitem>
- <para>
- Aktuell wird die <classname>Zend_Db::CASE_FOLDING</classname> Option vom
- Firebird/interbase Adapter nicht unterstützt. Nicht gequotete Identifizierer
- werden automatisch in Großschreibweise zurückgegeben.
- </para>
- </listitem>
- <listitem>
- <para>Der Name des Adapters ist ZendX_Db_Adapter_Firebird.</para>
- <para>
- Beachte das der Parameter adapterNamespace mit dem Wert ZendX_Db_Adapter
- zu verwenden ist.
- </para>
- <para>
- Wir empfehlen die gds32.dll (oder Ihr Linux Äquivalent) welche mit PHP
- ausgeliefert wird, auf die gleiche Version wie am Server hochzurüsten.
- Für Firebird ist das Äquivalent zu gds32.dll die fbclient.dll.
- </para>
- <para>
- Standardmäßig werden alle Identifikatoren (Tabellennamen, Felder) in
- Großschreibweise zurückgegeben.
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- </sect2>
- </sect1>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|