| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- EN-Revision: 15207 -->
- <!-- Reviewed: no -->
- <sect1 id="zend.db.table">
- <title>Zend_Db_Table</title>
- <sect2 id="zend.db.table.introduction">
- <title>Einführung</title>
- <para>
- Die <classname>Zend_Db_Table</classname> Klasse ist eine Objekt-Orientierte Schnittstelle zu Datenbank
- Tabellen. Sie bietet Methoden für viele gängige Operationen an Tabellen. Die
- Basisklasse ist erweiterbar, daher kann eigene Logik eingeführt werden.
- </para>
- <para>
- Die <classname>Zend_Db_Table</classname> Lösung ist eine Implementation des
- <ulink url="http://www.martinfowler.com/eaaCatalog/tableDataGateway.html">Table Data
- Gateway</ulink> Patterns. Die Lösung schließt außerdem eine Klasse ein, welche das
- <ulink url="http://www.martinfowler.com/eaaCatalog/rowDataGateway.html">Row Data
- Gateway</ulink> Pattern implementiert.
- </para>
- </sect2>
- <sect2 id="zend.db.table.defining">
- <title>Definieren einer Table Klasse</title>
- <para>
- Für jede Tabelle der Datenbank auf die zugegriffen werden soll, sollte eine eine Klasse
- erzeugt werden, welche <classname>Zend_Db_Table_Abstract</classname> erweitert.
- </para>
- <sect3 id="zend.db.table.defining.table-schema">
- <title>Definieren des Tabellennamens und Schemas</title>
- <para>
- Die Tabelle der Datenbank, für welche die Klasse bestimmt ist, wird mit der
- protected Variablen <code>$_name</code> angegeben. Es ist ein String, welcher den
- Namen der Tabelle enthalten muss, wie er in der Datenbank erscheint.
- </para>
- <example id="zend.db.table.defining.table-schema.example1">
- <title>Angeben einer Table Klasse mit ausdrücklichem Tabellennamen</title>
- <programlisting role="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs';
- }
- ]]></programlisting>
- </example>
- <para>
- Wird keine Tabellenname angegeben, so wird ein Standard verwendet, welcher dem
- Namen der Klasse entspricht. Wird sich auf diesen Standard verlassen, so muss der
- Klassenname der Schreibweise der Tabelle entsprechen, wie sie in der Datenbank
- erscheint.
- </para>
- <example id="zend.db.table.defining.table-schema.example">
- <title>Angeben einer Table Klasse mit inbegriffenem Tabellennamen</title>
- <programlisting role="php"><![CDATA[
- class bugs extends Zend_Db_Table_Abstract
- {
- // Tabellenname entspricht dem Klassennamen
- }
- ]]></programlisting>
- </example>
- <para>
- Es kann auch ein Schema für die Tabelle angegeben werden. Entweder mit der protected Variablen
- <code>$_schema</code> oder mit dem Schema vorangestellt in der <code>$_name</code> Eigenschaft.
- Jedes Schema welches in der <code>$_name</code> Eigenschatf angegeben ist wird vorrangig gegenüber
- dem Schema der <code>$_schema</code> Eigenschaft behandelt. In einigen RDBMS Marken ist die
- Bezeichnung für Schema "database" oder "tablespace", wird aber ähnlich verwendet.
- </para>
- <example id="zend.db.table.defining.table-schema.example3">
- <title>Angeben einer Table Klasse mit Schema</title>
- <programlisting role="php"><![CDATA[
- // Erste Möglichkeit:
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_schema = 'bug_db';
- protected $_name = 'bugs';
- }
- // Zweite Möglichkeit:
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bug_db.bugs';
- }
- // Wenn Schema sowohl in $_name als auch $_schema angegeben wird, so bekommt $_name vorrang:
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bug_db.bugs';
- protected $_schema = 'ignored';
- }
- ]]></programlisting>
- </example>
- <para>
- Die Schema und Tabellennamen können auch mit Konstruktor Konfigurationsdirektiven angegeben werden,
- welche jegliche Standardwerte, angegeben in den <code>$_name</code> und <code>$_schema</code>
- Eigenschaften, überschreiben. Eine Schema Angabe welche mit der <code>name</code> Directive
- angegeben wurde überschreibt jeglichen Wert welcher von der <code>schema</code> Option
- bereitgestellt ist.
- </para>
- <example id="zend.db.table.defining.table-schema.example.constructor">
- <title>Angebend von Tabellen und Schemanamen während der Instanziierung</title>
- <programlisting role="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- }
- // Erste Möglichkeit:
- $tableBugs = new Bugs(array('name' => 'bugs', 'schema' => 'bug_db'));
- // Zweite Möglichkeit:
- $tableBugs = new Bugs(array('name' => 'bug_db.bugs'));
- // Wenn Schema sowohl in $_name als auch $_schema angegeben wird,
- // so bekommt $_name vorrang:
- $tableBugs = new Bugs(array('name' => 'bug_db.bugs',
- 'schema' => 'ignored'));
- ]]></programlisting>
- </example>
- <para>
- Wenn kein Schemaname angegeben wird, so wird als Standard der Schemaname des Datenbankadapters
- verwendet.
- </para>
- </sect3>
- <sect3 id="zend.db.table.defining.primary-key">
- <title>Angeben des Primärschlüssels der Tabelle</title>
- <para>
- Jede Tabelle muss einen Primärschlüssel haben. Die Spalte des Primärschlüssels kann mit der
- protected Variablen <code>$_primary</code> angegeben werden. Sie enthält entweder einen String,
- welcher die einzelen Spalte benennt, oder ein Array von Spaltennamen, wenn der Primärschlüssel
- ein zusammengesetzter Schlüssel ist.
- </para>
- <example id="zend.db.table.defining.primary-key.example">
- <title>Beispiel für das spezifizieren eines Primärschlüssels</title>
- <programlisting role="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs';
- protected $_primary = 'bug_id';
- }
- ]]></programlisting>
- </example>
- <para>
- Wenn kein Primärschlüssel angegeben wird, versucht <classname>Zend_Db_Table_Abstract</classname> den Primärschlüssel mit
- Hilfe der <code>describeTable()</code> Methode zu ermitteln.
- </para>
- <note>
- <para>
- Jede Table Klasse muss wissen mit welche(r/n) Spalte(n) Zeilen eindeutig identifiziert werden
- können. Wenn keine Primärschlüssel Spalte(n) in der Klassendefinition oder als Argument für den
- Konstruktor angegeben wurde und nicht aus den Metadaten der Tabelle mit Hilfe der
- <code>describeTable()</code> Methode ermittelt werden kann, dann kann die Tabelle nicht mit
- <classname>Zend_Db_Table</classname> verwendet werden.
- </para>
- </note>
- </sect3>
- <sect3 id="zend.db.table.defining.setup">
- <title>Überschreiben von Table Setup Methoden</title>
- <para>
- Wenn eine Instanz einer Table Klasse erzeugt wird, ruft der Konstruktor einige protected Methoden
- auf, die Metadaten der Tabelle initialisieren. Jede dieser Methoden kann erweitert werden um
- Metadaten explizit anzugeben. Dabei darf nicht vergessen werden am Ende der eigenen Methode die
- gleichnamige Methode der Parentklasse aufzurufen.
- </para>
- <example id="zend.db.table.defining.setup.example">
- <title>Beispiel für das Überschreiben der _setupTableName() Methode</title>
- <programlisting role="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected function _setupTableName()
- {
- $this->_name = 'bugs';
- parent::_setupTableName();
- }
- }
- ]]></programlisting>
- </example>
- <para>
- Folgende Setup Methoden sind überschreibbar:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <code>_setupDatabaseAdapter()</code> überprüft ob ein Adapter bereitgestellt wird; nimmt
- einen Standardadapter aus der Registry, wenn benötigt. Durch das Überschreiben dieser
- Methode kann ein Datenbankadapter aus einer anderen Quelle gesetzt werden.
- </para>
- </listitem>
- <listitem>
- <para>
- <code>_setupTableName()</code> setzt den standard Tabellennamen auf den Namen der Klasse.
- Durch das Überschreiben dieser Methode kann der Tabellenname gesetzt werden bevor dieses
- Standardverhalten abläuft.
- </para>
- </listitem>
- <listitem>
- <para>
- <code>_setupMetadata()</code> setzt das Schema wenn der Tabellenname dem Muster
- "schema.table" entspricht; ruft <code>describeTable()</code> auf um Metadaten
- Informationen zu erhalten; Standardisiert das <code>$_cols</code> Array auf die
- Spalten wie von <code>describeTable()</code> geliefert. Durch das Überschreiben dieser
- Methode können die Spalten angegeben werden.
- </para>
- </listitem>
- <listitem>
- <para>
- <code>_setupPrimaryKey()</code> standardisiert die Primärschlüssel Spalten zu denen
- geliefert von <code>describeTable()</code>; prüft ob die Primärschlüssel Spalten
- im <code>$_cols</code> Array enthalten sind. Durch das Überschreiben dieser Methode
- können die Primärschlüssel Spalten angegeben werden.
- </para>
- </listitem>
- </itemizedlist>
- </sect3>
- <sect3 id="zend.db.table.initialization">
- <title>Tabellen Initialisierung</title>
- <para>
- Wenn Anwendungs-spezifische Logik initialisiert werden soll wenn eine Tabellenklasse
- erstellt wird, kann man entscheiden die Aufgaben in die <code>init()</code> Methode zu
- verschieben, die aufgerufen wird nachdem alle Tabellen Metadaten bearbeitet wurden. Das
- ist besser als die <code>__construct</code> Methode wenn die Metadaten nicht
- programmtechnisch verändert werden sollen.
- <example id="zend.db.table.defining.init.usage.example">
- <title>Beispielverwendung der init() Methode</title>
- <programlisting role="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_observer;
- public function init()
- {
- $this->_observer = new MyObserverClass();
- }
- }
- ]]></programlisting>
- </example>
- </para>
- </sect3>
- </sect2>
- <sect2 id="zend.db.table.constructing">
- <title>Erzeugen einer Instanz einer Tabelle</title>
- <para>
- Bevor eine Table Klasse verwendet werden kann muss eine Instanz mit dem Konstruktor erzeugt werden. Das
- Konstruktor Argument ist ein Array von Optionen. Die wichtigste Option für einen Tabellenkonstruktor
- ist die Instanz der Adapterklasse, welche eine live Verbindung zu einem RDBMS repräsentiert. Es gibt
- drei Möglichkeiten den Datenbankadapter einer Tabellenklasse anzugeben und diese sind unten
- beschrieben:
- </para>
- <sect3 id="zend.db.table.constructing.adapter">
- <title>Angeben eines Datenbankadapters</title>
- <para>
- Der erste Weg einen Datenbankadapter an eine Table Klasse bereitzustellen ist, ein Objekt des Typs
- <classname>Zend_Db_Adapter_Abstract</classname> im Options Array, bezeichnet mit dem Schlüssel <code>'db'</code>, zu
- übergeben.
- </para>
- <example id="zend.db.table.constructing.adapter.example">
- <title>Beispiel für das erzeugen einer Tabelle mit Nutzung eines Adapterobjekts</title>
- <programlisting role="php"><![CDATA[
- $db = Zend_Db::factory('PDO_MYSQL', $options);
- $table = new Bugs(array('db' => $db));
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.table.constructing.default-adapter">
- <title>Setzen eines Standard-Datenbankadapters</title>
- <para>
- Der zweite Weg einer Table Klasse einen Datenbankadapter bereit zu stellen ist es, ein Objekt des
- Typs <classname>Zend_Db_Adapter_Abstract</classname> zu deklarieren und als Standard für alle nachfolgenden Instanzen von
- Table der Applikation zu setzen. Dies kann mit der static Methode
- <classname>Zend_Db_Table_Abstract::setDefaultAdapter()</classname> getan werden. Das Argument ist ein
- Objekt des Typs <classname>Zend_Db_Adapter_Abstract</classname>.
- </para>
- <example id="zend.db.table.constructing.default-adapter.example">
- <title>Beispiel für das erstellen von Table mit einem Standardadapter</title>
- <programlisting role="php"><![CDATA[
- $db = Zend_Db::factory('PDO_MYSQL', $options);
- Zend_Db_Table_Abstract::setDefaultAdapter($db);
- // Später...
- $table = new Bugs();
- ]]></programlisting>
- </example>
- <para>
- Es kann geeignet sein den Datenbankadapter an einer zentralen Stelle der Anwendung, wie dem
- Bootstrap, zu erzeugen, und als Standardadapter zu speichern.
- Dies hilft sicher zu stellen, das der verwendete Adapter in der gesamten Anwendung der gleiche
- ist. Allerdings kann nur eine einzelne Adapterinstanz als Standardadapter verwendet werden.
- </para>
- </sect3>
- <sect3 id="zend.db.table.constructing.registry">
- <title>Speichern eines Datenbankadapters in der Registry</title>
- <para>
- Der dritte Weg einer Table Klasse einen Datenbankadapter bereit zu stellen ist es einen String in
- dem Optionsarray zu übergeben, auch mit dem <code>'db'</code> Schlüssel identifiziert. Der String
- wird als Schlüssel der statischen <classname>Zend_Registry</classname> Instanz verwendet, wo der Eintrag mit dem Schlüssel
- ein Objekt des Typs <classname>Zend_Db_Adapter_Abstract</classname> ist.
- </para>
- <example id="zend.db.table.constructing.registry.example">
- <title>Beispiel für das Erzeugen von Table mit einem Registry Schlüssel</title>
- <programlisting role="php"><![CDATA[
- $db = Zend_Db::factory('PDO_MYSQL', $options);
- Zend_Registry::set('my_db', $db);
- // Später...
- $table = new Bugs(array('db' => 'my_db'));
- ]]></programlisting>
- </example>
- <para>
- Wie das Setzen eines Standardadapters, bietet auch dieses sicher zu stellen das die gleiche Adapter
- Instanz in der gesamten Anwendung verwendet wird. Nutzen der Registry ist flexibler, da mehr als
- eine Adapterinstanz gepeichert werden kann. Eine angegebene Adapterinstanz ist spezifisch für eine
- bestimmte RDBMS Marke und Datenbankinstanz. Wenn die Anwendung Zugriff auf mehrere Datenbanken
- benötigt oder auch mehrere Datenbank Marken, dann müssen mehrere Adapter verwendet werden.
- </para>
- </sect3>
- </sect2>
- <sect2 id="zend.db.table.insert">
- <title>Zeilen in eine Tabelle einfügen</title>
- <para>
- Table Objekte können verwendet werden um Zeilen in die Datenbank Tabelle einzufügen auf der das
- Table Objekt basiert. Hierzu kann die <code>insert()</code> Methode des Table Objektes
- verwendet werden. Das Argument ist ein assoziatives Array, das Spalten Namen mit Werten verbindet.
- </para>
- <example id="zend.db.table.insert.example">
- <title>Beispiel für das Einfügen in eine Tabelle</title>
- <programlisting role="php"><![CDATA[
- $table = new Bugs();
- $data = array(
- 'created_on' => '2007-03-22',
- 'bug_description' => 'Irgendwas falsch',
- 'bug_status' => 'NEW'
- );
- $table->insert($data);
- ]]></programlisting>
- </example>
- <para>
- Standardmäßig werden Werte im Daten Array als literale Werte eingefügt durch das Verwenden von
- Parametern. Wenn es notwendig ist das diese als SQL Ausdruck behandelt werden, muß sichergestellt
- werden das Sie sich von reinen Strings unterscheiden. Es kann ein Objekt vom Typ <classname>Zend_Db_Expr</classname>
- verwendet werden um das zu bewerkstelligen.
- </para>
- <example id="zend.db.table.insert.example-expr">
- <title>Beispiel für das Einfügen von Ausdrücken in einer Tabelle</title>
- <programlisting role="php"><![CDATA[
- $table = new Bugs();
- $data = array(
- 'created_on' => new Zend_Db_Expr('CURDATE()'),
- 'bug_description' => 'Irgendwas ist falsch',
- 'bug_status' => 'NEU'
- );
- ]]></programlisting>
- </example>
- <para>
- Um obigen Beispiel vom Einfügen von Zeilen, wird angenommen das die Tabelle einen automatischen
- Primärschlüssel hat. Das ist das Standardverhalten von <classname>Zend_Db_Table_Abstract</classname>,
- aber es gibt auch andere Typen von Primärschlüssel. Das folgende Kapitel beschreibt wie
- verschiedene Typen von Primärschlüssel unterstützt werden.
- </para>
- <sect3 id="zend.db.table.insert.key-auto">
- <title>Eine Tabelle mit einem automatischen Primärschlüssel verwenden</title>
- <para>
- Ein automatischer Primärschlüssel erzeigt einen eindeutigen Integerwert wenn die
- Spalte des Primären Typs in der eigenen SQL <code>INSERT</code> Anweisung unterdrückt wird.
- </para>
- <para>
- Wenn die geschützte Variable <code>$_sequence</code>, in <classname>Zend_Db_Table_Abstract</classname>, als
- boolscher Wert <code>true</code> definiert wird, nimmt die Klasse an das die Tabelle
- einen automatischen Primärschlüssel hat.
- </para>
- <example id="zend.db.table.insert.key-auto.example">
- <title>Beispiel für das Deklarierens einer Tabelle mit einem automatischen Primärschlüssel</title>
- <programlisting role="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs';
- // Das ist der Standardwert in der Zend_Db_Table_Abstract Klasse;
- // er muß nicht definiert werden.
- protected $_sequence = true;
- }
- ]]></programlisting>
- </example>
- <para>
- MySQL, Microsoft SQL Server, und SQLite sind Beispiele von RDBMS Marken die automatische
- Primärschlüssel unterstützen.
- </para>
- <para>
- PostgreSQL hat eine <code>SERIAL</code> Notation die implizit eine Sequenz definiert die auf den
- Tabellen- und Spaltennamen basiert, und diese Sequenz verwendet, um einen Schlüsselwert für neue
- Zeilen zu erstellen. IBM DB2 hat eine <code>IDENTITY</code> Notation die ähnlich arbeitet.
- Wenn eine dieser Notationen verwendet wird, muß der <classname>Zend_Db_Table</classname> Klasse mitgeteilt werden das
- Sie eine automatische Spalte hat, indem <code>$_sequence</code> auf <code>true</code>
- gesetzt wird.
- </para>
- </sect3>
- <sect3 id="zend.db.table.insert.key-sequence">
- <title>Eine Tabelle mit einer Sequenz verwenden</title>
- <para>
- Eine Sequenz ist ein Datenbank Objekt das einen eindeutigen Wert erstellt, der als
- Wert des Primärschlüssels in einer oder mehreren Tabellen der Datenbank verwendet werden kann.
- </para>
- <para>
- Wenn <code>$_sequence</code> als String definiert wird, nimmt <classname>Zend_Db_Table_Abstract</classname> an das der
- String den Namen des Sequenz Objektes in der Datenbank benennt. Die Sequenz wird aufgerufen um
- einen neuen Wert zu erstellen, und dieser Wert wird in der <code>INSERT</code> Operation
- verwendet.
- </para>
- <example id="zend.db.table.insert.key-sequence.example">
- <title>Beispiel für das Deklaration einer Tabelle mit einer Sequenz</title>
- <programlisting role="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs';
- protected $_sequence = 'bug_sequence';
- }
- ]]></programlisting>
- </example>
- <para>
- Oracle, PostgreSQL, und IBM DB2 sind Beispiele von RDBMS Marken die Sequenz Objekte in der
- Datenbank unterstützen.
- </para>
- <para>
- PostgreSQL und IBM DB2 haben auch einen Syntax der Sequenzen implizit definiert und diese
- mit Spalten assoziiert. Wenn diese Notation verwendet wird, muß der Tabelle gesagt werden
- das Sie eine automatische Schlüsselspalte besitzt. Der Name der Sequenz muß
- nur in den Fällen als String definiert werden in denen die Sequenz explizit aufgerufen
- wird um den nächsten Schlüsselwert zu erhalten.
- </para>
- </sect3>
- <sect3 id="zend.db.table.insert.key-natural">
- <title>Eine Tabelle mit einem natürlichen Schlüssel verwenden</title>
- <para>
- Einige Tabellen haben natürliche Schlüssel. Das bedeutet das der Schlüssel nicht automatisch
- durch die Tabelle oder eine Sequenz erstellt wird. Der Wert für den Primärschlüssel muß
- in diesem Fall selbst definiert werden.
- </para>
- <para>
- Wenn <code>$_sequence</code> als boolsches <code>false</code> definiert wird, nimmt
- <classname>Zend_Db_Table_Abstract</classname> an das die Tabelle einen natürlichen Primärschlüssel hat. Es
- müssen Werte für die Spalte des Primärschlüssels im Array der Daten definiert werden die
- an die <code>insert()</code> Methode übergeben werden, andernfalls wird diese Methode eine
- <classname>Zend_Db_Table_Exception</classname> werfen.
- </para>
- <example id="zend.db.table.insert.key-natural.example">
- <title>Beispiel für das Definieren einer Tabelle mit einem natürlichen Schlüssel</title>
- <programlisting role="php"><![CDATA[
- class BugStatus extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bug_status';
- protected $_sequence = false;
- }
- ]]></programlisting>
- </example>
- <note>
- <para>
- Alle RDBMS Marken unterstützen Tabellen mit natürlichen Schlüsseln. Beispiele von Tabellen
- die oft so definiert werden das Sie natürliche Schlüssel besitzen sind Lookup Tabellen,
- Durchschnitts Tabellen in viele-zu-viele Beziehungen, oder die meisten Tabellen mit
- komponierten Primärschlüsseln.
- </para>
- </note>
- </sect3>
- </sect2>
- <sect2 id="zend.db.table.update">
- <title>Zeilen in einer Tabelle aktualisieren</title>
- <para>
- Spalten können in der Datenbanktabelle aktualisiert werden indem die <code>update</code>
- Methode der Table Klasse verwendet wird. Diese Methode nimmt zwei Argumente: ein
- assoziatives Array von Spalten die geändert werden sollen und neue Werte die diesen Spalten
- hinzugefügt werden; und einen SQL Ausdruck der in der <code>WHERE</code> Klausel verwendet wird,
- als Kriterium für die Zeilen die in der <code>UPDATE</code> Operation geändert werden sollen.
- </para>
- <example id="zend.db.table.update.example">
- <title>Beispiel für das Aktualisieren von Zeilen in einer Tabelle</title>
- <programlisting role="php"><![CDATA[
- $table = new Bugs();
- $data = array(
- 'updated_on' => '2007-03-23',
- 'bug_status' => 'FIXED'
- );
- $where = $table->getAdapter()->quoteInto('bug_id = ?', 1234);
- $table->update($data, $where);
- ]]></programlisting>
- </example>
- <para>
- Da die <code>update()</code> Methode der Tabelle zur
- <link linkend="zend.db.adapter.write.update"><code>update()</code></link> Methode des
- Datenbank Adapters weiterleitet, kann das zweite Argument ein Array von SQL Ausdrücken sein.
- Diese Ausdrücke werden als Boolsche Terme kombiniert indem ein <code>AND</code> Operator
- verwendet wird.
- </para>
- <note>
- <para>
- Die Werte und Identifizierer im SQL Ausdruck werden nicht in Anführungszeichen gesetzt.
- Wenn Werte oder Identifizierer vorhanden sind die das Setzen in Anführungszeichen
- benötigen, ist man selbst dafür zuständig das das getan wird. Die <code>quote()</code>,
- <code>quoteInto()</code> und <code>quoteIdentifier()</code> Methoden des Datenbank Adapters
- können dafür verwendet werden.
- </para>
- </note>
- </sect2>
- <sect2 id="zend.db.table.delete">
- <title>Zeilen aus einer Tabelle löschen</title>
- <para>
- Zeilen können von einer Datenbanktabelle gelöscht werden indem die <code>delete()</code>
- Methode verwendet wird. Diese Methode nimmt ein Argument, welches ein SQL Ausdruck ist,
- der in der <code>WHERE</code> Klausel als Kriterium dafür verwendet wird, welche Zeilen
- gelöscht werden sollen.
- </para>
- <example id="zend.db.table.delete.example">
- <title>Beispiel für das Löschen von Zeilen einer Tabelle</title>
- <programlisting role="php"><![CDATA[
- $table = new Bugs();
- $where = $table->getAdapter()->quoteInto('bug_id = ?', 1235);
- $table->delete($where);
- ]]></programlisting>
- </example>
- <para>
- Da die <code>delete()</code> Methode der Tabelle zur
- <link linkend="zend.db.adapter.write.delete"><code>delete()</code></link> Methode des Datenbank
- Adapters weiterleitet, kann das Argument ein Array von SQL Ausdrücken sein. Diese
- Ausdrücke werden als boolsche Terme kombiniert indem ein <code>AND</code> Operator verwendet wird.
- </para>
- <note>
- <para>
- Die Werte und Identifizierer im SQL Ausdruck werden nicht in Anführungszeichen gesetzt.
- Wenn Werte oder Identifizierer vorhanden sind die das Setzen in Anführungszeichen
- benötigen, ist man selbst dafür zuständig das das getan wird. Die <code>quote()</code>,
- <code>quoteInto()</code> und <code>quoteIdentifier()</code> Methoden des Datenbank Adapters
- können dafür verwendet werden.
- </para>
- </note>
- </sect2>
- <sect2 id="zend.db.table.find">
- <title>Zeilen durch den Primärschlüssel finden</title>
- <para>
- Die Datenbanktabelle kann nach passenden Zeilen für spezifizierte Werte im Primärschlüssel
- abgefragt werden, indem die <code>find()</code> Methode verwendet wird. Das erste Argument dieser
- Methode ist entweder ein einzelner Wert oder ein Array von Werten die dem Primärschlüssel dieser
- Tabelle entsprechen.
- </para>
- <example id="zend.db.table.find.example">
- <title>Beispiel für das Finden von Zeilen durch Werte des Primärschlüssels</title>
- <programlisting role="php"><![CDATA[
- $table = new Bugs();
- // Eine einzelne Zeile finden
- // Gibt ein Rowset zurück
- $rows = $table->find(1234);
- // Mehrere Zeilen finden
- // Gibt auch ein Rowset zurück
- $rows = $table->find(array(1234, 5678));
- ]]></programlisting>
- </example>
- <para>
- Wenn ein einzelner Wert spezifiziert wird, gibt die Methode auch maximal eine Zeile zurück, weil ein
- Primärschlüssel keinen doppelten Wert haben kann und es maximal eine Zeile in der Datenbank
- gibt die dem spezifizierten Wert entspricht. Wenn mehrere Werte in einem Array spezifiziert werden,
- gibt die Methode maximal soviele Zeilen zurück wie die Anzahl an unterschiedlichen Werten die
- spezifiziert wurden.
- </para>
- <para>
- Die <code>find()</code> Methode kann weniger Zeilen zurückgeben als die Anzahl an Werten die für
- den Primärschlüssel definiert wurden, wenn einige der Werte keiner Zeile in der Datenbank
- Tabelle entsprechen. Die Methode kann sogar null Zeilen zurückgeben. Weil die Anzahl an
- zurückgegebenen Zeilen variabel ist, gibt die <code>find()</code> Methode ein Objekt vom
- Typ <classname>Zend_Db_Table_Rowset_Abstract</classname> zurück.
- </para>
- <para>
- Wenn der Primärschlüssel ein komponierter Schlüssel ist, als einer der aus mehreren Spalten
- besteht, können die zusätzlichen Spalten als zusätzliche Argumente in der <code>find()</code>
- Methode definiert werden. Es müssen soviele Argumente angegeben werden wie Spalten im
- Primärschlüssel der Tabelle existieren.
- </para>
- <para>
- Um mehrere Zeilen von einer Tabelle mit einem kombinierten Primärschlüssel zu finden,
- muß ein Array für jedes der Argumente übergeben werden. Alle dieser Arrays müssen die gleiche
- Anzahl an Elementen haben. Die Werte in jedem Array werden in Tupeln geformt und gereiht; zum
- Beispiel definiert das erste Element in allen Array Argumenten den ersten kombinierten Wert
- des Primärschlüssels, das zweite Element von allen Arrays definiert den zweiten kombinierten
- Wert des Primärschlüssels, und so weiter.
- </para>
- <example id="zend.db.table.find.example-compound">
- <title>Beispiel für das Finden von Zeilen durch Werte von kombinierten Primärschlüsseln</title>
- <para>
- Der Aufruf von <code>find()</code> anbei um mehreren Zeilen zu entsprechen kann zwei Zeilen
- in der Datenbank entsprechen. Die erste Zeile muß den Wert des Primärenschlüssels (1234, 'ABC')
- haben, und die zweite Zeile den Wert des Primärschlüssels (5678, 'DEF').
- </para>
- <programlisting role="php"><![CDATA[
- class BugsProducts extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs_products';
- protected $_primary = array('bug_id', 'product_id');
- }
- $table = new BugsProducts();
- // Eine einzelne Zeilen mit einem kombinierten Primärschlüssel finden
- // Gibt ein Rowset zurück
- $rows = $table->find(1234, 'ABC');
- // Mehrere Zeilen mit einem kombinierten Primärschlüssel finden
- // Gibt auch ein Rowset zurück
- $rows = $table->find(array(1234, 5678), array('ABC', 'DEF'));
- ]]></programlisting>
- </example>
- </sect2>
- <sect2 id="zend.db.table.fetch-all">
- <title>Ein Set von Zeilen abfragen</title>
- <sect3 id="zend.db.table.fetch-all.select">
- <title>Select API</title>
- <para>
- <warning>
- <para>
- Die API für die Hol-Operationen wurde ausgeweitet um einem
- <classname>Zend_Db_Table_Select</classname> Objekt zu erlauben die Abfrage zu modifizieren.
- Trotzdem wird die veraltete Verwendung der <code>fetchRow()</code> und
- <code>fetchAll()</code> Methoden weiterhin ohne Änderungen funktionieren.
- </para>
- <para>
- Die folgenden Ausdrücke sind gültig und funktionell identisch, trotzdem wird
- empfohlen den Code zu aktualisieren um Vorteil aus der neuen Verwendung zu
- ziehen wo das möglich ist.
- </para>
- <para>
- <programlisting role="php"><![CDATA[
- // Ein Rowset holen
- $rows = $table->fetchAll('bug_status = "NEW"', 'bug_id ASC', 10, 0);
- $rows = $table->fetchAll($table->select()->where('bug_status = ?', 'NEW')
- ->order('bug_id ASC')
- ->limit(10, 0));
- // Eine einzelne Zeile holen
- $row = $table->fetchRow('bug_status = "NEW"', 'bug_id ASC');
- $row = $table->fetchRow($table->select()->where('bug_status = ?', 'NEW')
- ->order('bug_id ASC'));
- ]]></programlisting>
- </para>
- </warning>
- </para>
- <para>
- Das <classname>Zend_Db_Table_Select</classname> Objekt ist eine Erweiterung des
- <classname>Zend_Db_Select</classname> Objekts das spezielle Einschränkungen zu einer
- Abfrage hinzufügt. Die Verbesserungen und Einschränkungen sind folgende:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- Man <emphasis>kann</emphasis> sich entscheiden ein Subset von Zeilen einer
- fetchRow oder fetchAll Abfrage zurückzuerhalten. Dann kann Vorteile durch
- Optimierung bieten, wenn die Rückgabe eines großes Sets an Ergebnissen für
- alle Zeilen nicht gewünscht wird.
- </para>
- </listitem>
- <listitem>
- <para>
- Man <emphasis>kann</emphasis> Zeilen spezifizieren die Ausdrücke innerhalb der
- ausgewählten Tabelle evaluieren. Trotzdem bedeutet das, das die zurückgegebene Zeile
- oder Zeilenset <property>readOnly</property> (nur lesbar) ist und nicht für
- save() Operationen verwendet werden kann. Eine <classname>Zend_Db_Table_Row</classname>
- mit <property>readOnly</property> Status wird eine Exception werfen wenn eine
- <code>save()</code> Operation versucht wird.
- </para>
- </listitem>
- <listitem>
- <para>
- Man <emphasis>kann</emphasis> JOIN Klauseln auf einer Auswahl erlauben um
- Mehrfach-Tabellen Lookups zu erlauben.
- </para>
- </listitem>
- <listitem>
- <para>
- Man <emphasis>kann keine</emphasis> Spalten von einer geJOINten Tabelle
- spezifizieren damit Sie in einer Zeile/Zeilenset zurückgegeben werden. Wenn
- das versucht wird, wird ein PHP Fehler getriggert. Das wurde getan um
- Sicherzustellen das die Integrität von <classname>Zend_Db_Table gewahrt
- bleibt</classname>. z.B. ein <classname>Zend_Db_Table_Row</classname> sollte nur Spalten
- referenzieren die von seiner Elterntabelle abgeleitet sind.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- <example id="zend.db.table.qry.rows.set.simple.usage.example">
- <title>Einfache Verwendung</title>
- <programlisting role="php"><![CDATA[
- $table = new Bugs();
- $select = $table->select();
- $select->where('bug_status = ?', 'NEW');
- $rows = $table->fetchAll($select);
- ]]></programlisting>
- </example>
- </para>
- <para>
- Flüssige Interfaces sind über alle Komponenten hinweg implementiert, sodas das zu einer
- mehr abgekürzteren Form umgeschrieben werden kann.
- </para>
- <para>
- <example id="zend.db.table.qry.rows.set.fluent.interface.example">
- <title>Example of fluent interface</title>
- <programlisting role="php"><![CDATA[
- $table = new Bugs();
- $rows =
- $table->fetchAll($table->select()->where('bug_status = ?', 'NEW'));
- ]]></programlisting>
- </example>
- </para>
- </sect3>
- <sect3 id="zend.db.table.fetch-all.usage">
- <title>Ein Set von Zeilen abfragen</title>
- <para>
- Ein Set von Zeilen kann abgefragt werden indem irgendein Kriterium verwendet wird, das anders als
- die Werte des Primärschlüssels sind, indem die <code>fetchAll()</code> Methode der Tabellen
- Klasse verwendet wird. Diese Methode gibt ein Objekt vom Typ
- <classname>Zend_Db_Table_Rowset_Abstract</classname> zurück.
- </para>
- <example id="zend.db.table.qry.rows.set.finding.row.example">
- <title>Beispiel für das Finden von Zeilen durch einen Ausdruck</title>
- <programlisting role="php"><![CDATA[
- $table = new Bugs();
- $select = $table->select()->where('bug_status = ?', 'NEW');
- $rows = $table->fetchAll($select);
- ]]></programlisting>
- </example>
- <para>
- Der <code>ORDER BY</code> kann auch ein Sortier-Kriterium übergeben werden, genauso
- wie auch Count und Offset Integer Werte, verwendet werden können damit die Abfrage
- ein spezielles Subset von Zeilen zurück gibt. Diese Werte werden in einer
- <code>LIMIT</code> Klausel verwendet oder in einer ähnlichen Logik für RDBMS Marken
- die die <code>LIMIT</code> Syntax nicht unterstützen.
- </para>
- <example id="zend.db.table.fetch-all.example2">
- <title>Beispiel für das Finden von Zeilen durch einen Ausdruck</title>
- <programlisting role="php"><![CDATA[
- $table = new Bugs();
- $order = 'bug_id';
- // Gibt die Zeilen 21 bis 30 zurück
- $count = 10;
- $offset = 20;
- $select = $table->select()->where(array('bug_status = ?' => 'NEW'))
- ->order($order)
- ->limit($count, $offset);
- $rows = $table->fetchAll($select);
- ]]></programlisting>
- </example>
- <para>
- Alle diese Argumente sind optional. Wenn die ORDER Klausel unterdrückt wird, dann
- enthält das Ergebnis die Zeilen der Tabelle in einer unvorhersagbaren Reihenfolge.
- Wenn keine LIMIT Klausel gesetzt ist, dann wird jede Zeile dieser Tabelle
- zurückgegeben die der WHERE Klausen entspricht.
- </para>
- </sect3>
- <sect3 id="zend.db.table.advanced.usage">
- <title>Fortgeschrittene Verwendung</title>
- <para>
- Für speziellere und optimierte Ergebnisse, kann es gewünscht sein die Anzahl der
- zurückgegebenen Zeilen/Sets zu limitieren. Das kann durch die Übergabe einer FROM
- Klausel an das Select Objekt getan werden. Das erste Argument in der FROM Klausel
- ist identisch mit den des <classname>Zend_Db_Select</classname> Objekts wobei man zusätzlich eine Instanz
- von <classname>Zend_Db_Table_Abstract</classname> übergeben und damit den Tabellen Namen automatisch
- ermitteln lassen kann.
- </para>
- <para>
- <example id="zend.db.table.qry.rows.set.retrieving.a.example">
- <title>Spezielle Spalten erhalten</title>
- <programlisting role="php"><![CDATA[
- $table = new Bugs();
- $select = $table->select();
- $select->from($table, array('bug_id', 'bug_description'))
- ->where('bug_status = ?', 'NEW');
- $rows = $table->fetchAll($select);
- ]]></programlisting>
- </example>
- </para>
- <para>
- <important>
- <para>
- Das Rowset enthält Zeilen die trotzdem 'gültig' sind - sie enthalten bloß
- ein Subset der Spalten einer Tabelle. Wenn eine save() Methode auf dem Teil
- einer Zeile aufgerufen wird dann werden nur die vorhandenen Felder geändert.
- aufgerufen
- </para>
- </important>
- Es können Ausdrücke in einer FROM Klausel spezifiziert werden die dann als readOnly
- Zeile/Set zurückgegeben werden. In diesem Beispiel werden Zeilen von der Bugs
- Tabelle zurückgegeben die einen Bereich von Nummern neuer Bugs zeigen die von
- Individuen mitgeteilt wurden. Die GROUP Klausel ist zu beachten. Die 'count' Spalte
- wird der Zeile für Evaluation angefügt und es kann auch Sie zugegriffen werden wie
- wenn Sie ein Teil des Schemas wäre.
- </para>
- <para>
- <example id="zend.db.table.qry.rows.set.retrieving.b.example">
- <title>Ausdrücke als Spalten erhalten</title>
- <programlisting role="php"><![CDATA[
- $table = new Bugs();
- $select = $table->select();
- $select->from($table,
- array('COUNT(reported_by) as `count`', 'reported_by'))
- ->where('bug_status = ?', 'NEW')
- ->group('reported_by');
- $rows = $table->fetchAll($select);
- ]]></programlisting>
- </example>
- Es kann auch ein Lookup als Teil der Abfrage verwendet werden um die Fetch
- Operation zu verfeinern. In diesem Beispiel wird die Accounts Tabelle als Teil
- einer Suche nach allen Bugs die von 'Bob' gemeldet wurden, abgefragt.
- </para>
- <para>
- <example id="zend.db.table.qry.rows.set.refine.example">
- <title>Beispiel für das Finden von Zeilen durch einen Ausdruck</title>
- <programlisting role="php"><![CDATA[
- $table = new Bugs();
- $select = $table->select();
- $select->where('bug_status = ?', 'NEW')
- ->join('accounts', 'accounts.account_name = bugs.reported_by')
- ->where('accounts.account_name = ?', 'Bob');
- $rows = $table->fetchAll($select);
- ]]></programlisting>
- </example>
- </para>
- <para>
- <classname>Zend_Db_Table_Select</classname> wird primär verwendet um zu verbinden
- und zu prüfen um die Kriterien für einen legalen SELECT Query sicherzustellen.
- Trotzdem gibt es viele Fälle in denen man die Flexibilität der <classname>Zend_Db_Table_Row</classname>
- benötigt und Zeilen nicht geschrieben oder gelöscht werden müssen. Für diesen
- speziellen Fall ist es möglich Zeilen/-sets durch die Übergabe eines false Wertes
- an setIntegrityCheck zu erhalten. Das resultierende Zeilen/-set wird als eine
- 'locked' Zeile zurückgegeben (das bedeutet das save(), delete() und jede andere
- Mothode die Felder setzt wird eine Ausnahme werfen).
- </para>
- <example id="zend.db.table.qry.rows.set.integrity.example">
- <title>Entfernen des Integritäts Checks von Zend_Db_Table_Select um geJOINte Zeilen zu erlauben</title>
- <programlisting><![CDATA[
- $table = new Bugs();
- $select = $table->select()->setIntegrityCheck(false);
- $select->where('bug_status = ?', 'NEW')
- ->join('accounts',
- 'accounts.account_name= bugs.reported_by',
- 'account_name')
- ->where('accounts.account_name = ?', 'Bob');
- $rows = $table->fetchAll($select);
- ]]></programlisting>
- </example>
- </sect3>
- </sect2>
- <sect2 id="zend.db.table.fetch-row">
- <title>Eine einzelne Zeilen abfragen</title>
- <para>
- Eine einzelne Zeile kann abgefragt werden indem Kriterien verwendet werden die ähnlich denen
- der <code>fetchAll()</code> Methode sind.
- </para>
- <example id="zend.db.table.fetch-row.example1">
- <title>Beispiel für das Finden einer einzelnen Zeilen durch einen Ausdruck</title>
- <programlisting role="php"><![CDATA[
- $table = new Bugs();
- $select = $table->select()->where('bug_status = ?', 'NEW')
- ->order('bug_id');
- $row = $table->fetchRow($select);
- ]]></programlisting>
- </example>
- <para>
- Diese Methode gibt ein Objekt vom Typ <classname>Zend_Db_Table_Row_Abstract</classname> zurück. Wenn die spezifizierten
- Sortier-Kriterien keiner Zeile in der Datenbank Tabelle entsprechen gibt <code>fetchRow()</code>
- PHP's <code>null</code> Wert zurück.
- </para>
- </sect2>
- <sect2 id="zend.db.table.info">
- <title>Informationen der Tabellen Metadaten erhalten</title>
- <para>
- Die <classname>Zend_Db_Table_Abstract</classname> Klasse bietet einige Informationen über Ihre Metadaten. Die
- <code>info()</code> Methode gibt eine Array Struktur mit Informationen über die Tabelle, Ihre
- Spalten und Primärschlüssel zurück, sowie andere Metadaten.
- </para>
- <example id="zend.db.table.info.example">
- <title>Beispiel für das Erhalten des Namens einer Tabelle</title>
- <programlisting role="php"><![CDATA[
- $table = new Bugs();
- $info = $table->info();
- echo "Der Name der Tabelle ist " . $info['name'] . "\n";
- ]]></programlisting>
- </example>
- <para>
- Die Schlüssel des Arrays das von der <code>info()</code> Methode zurückgegeben wird sind
- anbei beschrieben:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis role="strong">name</emphasis> => der Name der Tabelle.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">cols</emphasis> => ein Array das die Spalte(n) der Tabelle benennt.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">primary</emphasis> => ein Array das die Spalte(n) des Primärschlüssels
- benennt.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">metadata</emphasis> => ein assoziatives Array das die Spaltennamen
- mit Informationen über die Spalten zusammenführt. Das ist die Information die durch die
- <code>describeTable()</code> Methode zurückgegeben wird.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">rowClass</emphasis> => der Name der konkreten Klasse die für
- Zeilen Objekte verwendet wird und von den Methoden dieser Table Instanz zurückgegeben
- wird. Der Standardwert ist <classname>Zend_Db_Table_Row</classname>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">rowsetClass</emphasis> => Name der konkreten Klasse für für
- Rowset Objekte verwendet wird und von den Methoden dieser Table Instanz zurückgegeben
- wird. Der Standardwert ist <classname>Zend_Db_Table_Rowset</classname>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">referenceMap</emphasis> => ist ein assoziatives Array von
- Klassennamen von Tabellen die diese Tabelle referenzieren. Siese
- <xref linkend="zend.db.table.relationships.defining" />.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">dependentTables</emphasis> => ein Array von Klassennamen von
- Tabellen die diese Tabelle referenzieren. Siese
- <xref linkend="zend.db.table.relationships.defining" />.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">schema</emphasis> => der Name des Schemas (oder der
- Datenbank oder dem Tabellenraum) für diese Tabelle.
- </para>
- </listitem>
- </itemizedlist>
- </sect2>
- <sect2 id="zend.db.table.metadata.caching">
- <title>Tabellen Metadaten cachen</title>
- <para>
- Standardmäßig fragt <classname>Zend_Db_Table_Abstract</classname> die darunterliegende Datenbank für die
- <link linkend="zend.db.table.info">Metadaten der Tabelle</link> ab immer wenn diese diese Daten
- benötigt werden um Tabellenoperationen durchzuführen. Das Tableobjekt holt die Metadaten der
- Tabelle von der Datenbank indem es die <code>describeTable()</code> Methode des Adapters
- verwendet. Operationen die diese Einsicht benötigten sind:
- </para>
- <itemizedlist>
- <listitem><para><code>insert()</code></para></listitem>
- <listitem><para><code>find()</code></para></listitem>
- <listitem><para><code>info()</code></para></listitem>
- </itemizedlist>
- <para>
- In einigen Fällen, speziell wenn viele Table Objekte auf der gleichen Datenbanktabelle instanziert
- werden kann das Abfragen der Datenbank nach den Metadaten der Tabelle für jede Instanz unerwünscht
- sein wegen der Geschwindigkeit. In solchen Fällen, können Benutzer davon profitieren das
- die Metadaten der Tabelle, die von der Datenbank empfangen werden, gecached werden.
- </para>
- <para>
- Es gibt zwei grundsätzliche Wege bei denen ein Benutzer Vorteile davon haben kann wenn die
- Metadaten der Tabelle gecached werden:
- <itemizedlist>
- <listitem>
- <para>
- <emphasis role="strong">Aufruf von <classname>Zend_Db_Table_Abstract::setDefaultMetadataCache()</classname></emphasis> -
- Das erlaubt es Entwicklern das Standardcacheobjekt zu setzen das für alle Tabellenklassen
- verwendet werden soll.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis role="strong">Konfigurieren von <classname>Zend_Db_Table_Abstract::__construct()</classname></emphasis> -
- Das erlaubt es Entwicklern das Cacheobjekt zu setzen das für eine spezielle Instanz
- der Tabellenklasse verwendet werden soll.
- </para>
- </listitem>
- </itemizedlist>
- In beiden Fällen muß die Spezifikation des Caches entweder <code>null</code> (wenn kein Cache
- verwendet wird) oder eine Instanz von
- <link linkend="zend.cache.frontends.core"><classname>Zend_Cache_Core</classname></link> sein. Die Methoden
- können in Verbindung zueinander verwendet werden wenn es gewünscht ist beides zu haben, einen
- standardmäßigen Cache für die Metadaten und die Möglichkeit den Cache eines individuellen
- Tabellenobjektes zu ändern.
- </para>
- <example id="zend.db.table.metadata.caching-default">
- <title>Verwenden eines standardmäßigen Caches für Metadaten für alle Tabellenobjekte</title>
- <para>
- Der folgende Code demonstriert wie ein standardmäßiger Cache für die Metadaten gesetzt werden
- kann der für alle Tabellenobjekte verwendet wird:
- </para>
- <programlisting role="php"><![CDATA[<
- // Zuerst muß der Cache vorbereitet werden
- $frontendOptions = array(
- 'automatic_serialization' => true
- );
- $backendOptions = array(
- 'cache_dir' => 'cacheDir'
- );
- $cache = Zend_Cache::factory('Core',
- 'File',
- $frontendOptions,
- $backendOptions);
- // Als nächstes, den Cache setzen der mit allen Tabellenobjekten verwendet werden soll
- Zend_Db_Table_Abstract::setDefaultMetadataCache($cache);
- // Eine Tabellenklasse wird auch benötigt
- class Bugs extends Zend_Db_Table_Abstract
- {
- // ...
- }
- // Jede Instanz von Bugs verwenden nur den Standardmäßigen Cache fpr die Metadaten
- $bugs = new Bugs();
- ]]></programlisting>
- </example>
- <example id="zend.db.table.metadata.caching-instance">
- <title>Einen Metadaten Cache für ein spezielles Tabellenobjekt verwenden</title>
- <para>
- Der folgende Code demonstriert wie ein Cache für Metadaten für eine spezielle Instanz
- eines Tabellenobjektes gesetzt werden kann:
- </para>
- <programlisting role="php"><![CDATA[
- // Zuerst den Cache vorbereiten
- $frontendOptions = array(
- 'automatic_serialization' => true
- );
- $backendOptions = array(
- 'cache_dir' => 'cacheDir'
- );
- $cache = Zend_Cache::factory('Core',
- 'File',
- $frontendOptions,
- $backendOptions);
- // Eine Tabellenklasse wird auch benötigt
- class Bugs extends Zend_Db_Table_Abstract
- {
- // ...
- }
- // Eine Instanz für die Instanzierung konfgurieren
- $bugs = new Bugs(array('metadataCache' => $cache));
- ]]></programlisting>
- </example>
- <note>
- <title>Automatische Serialisierung mit dem Cache Frontend</title>
- <para>
- Da die Information die von der describeTable() Methode des Adapters zurückgegeben wird, ein
- Array ist, muß sichergestellt werden das die <code>automatic_serialization</code> Option für das
- <classname>Zend_Cache_Core</classname> Frontend auf <code>true</code> gesetzt wird.
- </para>
- </note>
- <para>
- Obwohl die obigen Beispiele <classname>Zend_Cache_Backend_File</classname> verwenden, können Entwickler
- jegliches Cache Backend verwenden das der Situation am besten entspricht. Siehe
- <link linkend="zend.cache">Zend_Cache</link> für weitere Informationen.
- </para>
- <sect3 id="zend.db.table.metadata.caching.hardcoding">
- <title>Tabellen Metadaten hardcoden</title>
- <para>
- Um das Cachen von Metadaten einen weiteren Schritt weiterzubringen, kann man sich auch
- entscheiden die Metadaten hardzucoden. In diesem speziellen Fall benötigt jede Änderung
- trotzdem eine Änderung im Code. Als solches, ist es nur empfohlen für jene die eine
- Produktionsumgebung optimieren wollen.
- </para>
- <para>
- Die Struktur der Metadaten ist wie folgt:
- </para>
- <programlisting role="php"><![CDATA[
- protected $_metadata = array(
- '<column_name>' => array(
- 'SCHEMA_NAME' => <string>,
- 'TABLE_NAME' => <string>,
- 'COLUMN_NAME' => <string>,
- 'COLUMN_POSITION' => <int>,
- 'DATA_TYPE' => <string>,
- 'DEFAULT' => NULL|<value>,
- 'NULLABLE' => <bool>,
- 'LENGTH' => <string - length>,
- 'SCALE' => NULL|<value>,
- 'PRECISION' => NULL|<value>,
- 'UNSIGNED' => NULL|<bool>,
- 'PRIMARY' => <bool>,
- 'PRIMARY_POSITION' => <int>,
- 'IDENTITY' => <bool>,
- ),
- // additional columns...
- );
- ]]></programlisting>
- <para>
- Ein einfacher Weg um die richtigen Werte zu erhalten ist es den Metadaten Cache zu verwenden,
- und dann die Werte die im Cache gespeichert sind, zu deserialisieren.
- </para>
- <para>
- Diese Optimierung kann ausgeschaltet werden indem das <code>metadataCacheInClass</code>
- Flag ausgeschaltet wird:
- </para>
- <programlisting role="php"><![CDATA[
- // Bei der Instanziierung:
- $bugs = new Bugs(array('metadataCacheInClass' => false));
- // Oder später:
- $bugs->setMetadataCacheInClass(false);
- ]]></programlisting>
- <para>
- Das Flag ist standardmäßig aktiviert, was sicherstellt das das <code>$_metadata</code>
- Array nur einmal pro Instanz ausgeliefert wird.
- </para>
- </sect3>
- </sect2>
- <sect2 id="zend.db.table.extending">
- <title>Eine Table Klasse erweitern und anpassen</title>
- <sect3 id="zend.db.table.extending.row-rowset">
- <title>Verwenden eigener Zeilen oder Rowset Klassen</title>
- <para>
- Standardmäßig geben die Methoden der Table Klasse ein Rowset als Instanzen der konkreten Klasse
- <classname>Zend_Db_Table_Rowset</classname>, und Rowsets enthalten eine Kollektion von Instanzen der konkreten Klasse
- <classname>Zend_Db_Table_Row</classname>. Eine alternative Klasse kann für jede von Ihnen als alternative Klasse
- definiert werden die verwendet werden soll, aber es müssen Klassen sein die
- <classname>Zend_Db_Table_Rowset_Abstract</classname> erweitern und respektiv <classname>Zend_Db_Table_Row_Abstract</classname>.
- </para>
- <para>
- Es können Zeilen und Rowset Klassen definiert werden indem das Optionsarray des Table
- Konstruktors verwendet wird, respektiv die Schlüssel <code>'rowClass'</code> und
- <code>'rowsetClass'</code>. Die Namen der Klassen müssen spezifiziert werden indem Strings
- verwendet werden.
- </para>
- <example id="zend.db.table.extending.row-rowset.example">
- <title>Beispiel dafür wie die Zeilen und Rowset Klassen spezifiziert werden können</title>
- <programlisting role="php"><![CDATA[
- class My_Row extends Zend_Db_Table_Row_Abstract
- {
- ...
- }
- class My_Rowset extends Zend_Db_Table_Rowset_Abstract
- {
- ...
- }
- $table = new Bugs(
- array(
- 'rowClass' => 'My_Row',
- 'rowsetClass' => 'My_Rowset'
- )
- );
- $where = $table->getAdapter()->quoteInto('bug_status = ?', 'NEW')
- // Gibt ein Objekt des Typs My_Rowset zurück
- // das ein Array von Objekten des Typs My_Row enthält.
- $rows = $table->fetchAll($where);
- ]]></programlisting>
- </example>
- <para>
- Die Klassen können geändert werden indem Sie mit den <code>setRowClass()</code> und
- <code>setRowsetClass()</code> Methoden spezifiziert werden. Das entspricht den Zeilen
- und Rowsets die nachfolgend erstellt werden; es ändert aber nicht die Klasse von Zeilen-
- oder Rowsetobjekten die bereits davor erstellt wurden.
- </para>
- <example id="zend.db.table.extending.row-rowset.example2">
- <title>Beispiel für das Ändern von Zeilen und Rowset Klassen</title>
- <programlisting role="php"><![CDATA[
- $table = new Bugs();
- $where = $table->getAdapter()->quoteInto('bug_status = ?', 'NEW')
- // Gibt ein Objekt vom Typ Zend_Db_Table_Rowset zurück das ein Array
- // von Objekten des Typs Zend_Db_Table_Row enthält.
- $rowsStandard = $table->fetchAll($where);
- $table->setRowClass('My_Row');
- $table->setRowsetClass('My_Rowset');
- // Gibt ein Objekt vom Typ My_Rowset zurück das ein Array
- // von Objekten des Typs My_Row enthält.
- $rowsCustom = $table->fetchAll($where);
- // Das $rowsStandard Objekt existiert noch immer, und es bleibt unverändert.
- ]]></programlisting>
- </example>
- <para>
- Für weitere Informationen über Zeilen und Rowset Klassenm siehe
- <xref linkend="zend.db.table.row" /> und <xref linkend="zend.db.table.rowset" />.
- </para>
- </sect3>
- <sect3 id="zend.db.table.extending.insert-update">
- <title>Selbst definierte Logik für das Einfügen, Aktualisieren und Löschen</title>
- <para>
- Die <code>insert()</code> und <code>update()</code> Methoden in der Table Klasse können
- überschrieben werden. Das bietet die Möglichkeit eigenen Code einzufügen der ausgeführt
- wird bevor die Datenbank Operation durchgeführt wird. Es muß sichergestellt werden das die
- Methode der Elternklasse aufgerufen wird wenn man fertig ist.
- </para>
- <example id="zend.db.table.extending.insert-update.example">
- <title>Eigene Logik um Zeitstempel zu managen</title>
- <programlisting role="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs';
- public function insert(array $data)
- {
- // Einen Zeitstempel hinzufügen
- if (empty($data['created_on'])) {
- $data['created_on'] = time();
- }
- return parent::insert($data);
- }
- public function update(array $data, $where)
- {
- // Einen Zeitstempel hinzufügen
- if (empty($data['updated_on'])) {
- $data['updated_on'] = time();
- }
- return parent::update($data, $where);
- }
- }
- ]]></programlisting>
- </example>
- <para>
- Auch die <code>delete()</code> Methode kann überschrieben werden.
- </para>
- </sect3>
- <sect3 id="zend.db.table.extending.finders">
- <title>Eigene Such Methoden in Zend_Db_Table definieren</title>
- <para>
- Es können eigene Abfrage Methoden in der Table Klasse implementiert werden, wenn oft die
- Notwendigkeit besteht Abragen mit speziellen Kriterien auf der Table Klasse durchzuführen.
- Die meisten Abfragen können mit <code>fetchAll()</code> geschrieben werden, das bedeutet aber
- das Code dupliziert werden muß um Abfragekonditionen zu formen die Abfrage in verschiedenen
- Orten der Anwendung auszuführen. Hierfür kann es nützlich sein eine Methode in der Table Klasse
- zu definieren um oft benutzte Abfragen an dieser Tabelle durchzuführen.
- </para>
- <example id="zend.db.table.extending.finders.example">
- <title>Eigene Methode um Fehler durch den Status zu finden</title>
- <programlisting role="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs';
- public function findByStatus($status)
- {
- $where = $this->getAdapter()->quoteInto('bug_status = ?', $status);
- return $this->fetchAll($where, 'bug_id');
- }
- }
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.table.extending.inflection">
- <title>Inflection (Beugung) in Zend_Db_Table definieren</title>
- <para>
- Einige Leute bevorzugen das der Name der Table Klasse einem Tabellennamen in der RDBMS, durch
- eine Stringumwandlung die <emphasis>Inflection</emphasis> (Beugung) genannt wird, entspricht.
- </para>
- <para>
- Wenn zum Beispiel der Name der Table Klasse "<code>BugsProducts</code>" ist, würde Sie der
- physikalischen Tabelle in der Datenbank entsprechen die "<code>bugs_products</code>" heißt,
- wenn die explizite Definition der <code>$_name</code> Eigenschaft der Klasse unterdrückt wird.
- In dieser Übereinstimmung der Beugung, wird der Klassenname im "CamelCase" Format geschrieben
- und in Kleinschreibung transformiert, und Wörter mit einem Unterstrich seperiert.
- </para>
- <para>
- Der Tabellenname der Datenbank kann unabhängig vom Klassennamen spezifiziert werden indem der
- Tabellenname mit der Klasseneigenschaft <code>$_name</code> in jeder der eigenen Tabellenklassen
- deklariert wird.
- </para>
- <para>
- <classname>Zend_Db_Table_Abstract</classname> führt keine Beugung durch um die Klassennamen mit den Tabellennamen
- in Übereinstimmung zu bringen. Wenn die Deklaration von <code>$_name</code> in der eigenen
- Tabellenklasse unterdrückt wird, wird die Klasse mit der Datenbanktabelle in Verbindung
- gebracht die der Schreibweise des Klassennamens exakt entspricht.
- </para>
- <para>
- Es ist unzureichend Identifizierer von der Datenbank zu transformieren, da das zu
- Doppeldeutigkeiten führen kann oder einige Identifizierer sogar unerreichbar macht.
- Die Verwendung der SQL Identifizierer exakt so wie Sie in der Datenbank vorhanden sind,
- macht <classname>Zend_Db_Table_Abstract</classname> sowohl einfacher als auch flexibler.
- </para>
- <para>
- Wenn man es vorzieht Beugung zu verwenden, muß die Transformation selbst durch das
- Überschreiben der <code>_setupTableName()</code> Methode in der eigenen Tabellenklasse
- implementiert werden. Ein Weg um das zu tun ist die Definition einer abstrakten Klase die
- <classname>Zend_Db_Table_Abstract</classname> erweitert. Der Rest der eigenen Klassen erweitert dann die eigene
- neue abstrakte Klasse.
- </para>
- <example id="zend.db.table.extending.inflection.example">
- <title>Beispiel einer abstrakten Tabellenklasse die Beugung implementiert</title>
- <programlisting role="php"><![CDATA[
- abstract class MyAbstractTable extends Zend_Db_Table_Abstract
- {
- protected function _setupTableName()
- {
- if (!$this->_name) {
- $this->_name = myCustomInflector(get_class($this));
- }
- parent::_setupTableName();
- }
- }
- class BugsProducts extends MyAbstractTable
- {
- }
- ]]></programlisting>
- </example>
- <para>
- Man ist selbst für das Schreiben von Funktionen verantwortlich um die Transformation der
- Beugung auszuführen. Zend Framework bietet solche Funktionen nicht an.
- </para>
- </sect3>
- </sect2>
- </sect1>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|