[MANUAL] German:
[zend.git] / documentation / manual / de / module_specs / Zend_Db_Table.xml
blobde2ea9143e4ae5c1b4958893a1f2d793de73fab6
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!-- EN-Revision: 21597 -->
3 <!-- Reviewed: no -->
4 <sect1 id="zend.db.table">
5     <title>Zend_Db_Table</title>
7     <sect2 id="zend.db.table.introduction">
8         <title>Einführung</title>
10         <para>
11             Die <classname>Zend_Db_Table</classname> Klasse ist eine Objekt-Orientierte
12             Schnittstelle zu Datenbank Tabellen. Sie bietet Methoden für viele gängige Operationen
13             an Tabellen. Die Basisklasse ist erweiterbar, daher kann eigene Logik eingeführt werden.
14         </para>
16         <para>
17             Die <classname>Zend_Db_Table</classname> Lösung ist eine Implementation des
18             <ulink url="http://www.martinfowler.com/eaaCatalog/tableDataGateway.html">Table Data
19             Gateway</ulink> Patterns. Die Lösung schließt außerdem eine Klasse ein, welche das
20             <ulink url="http://www.martinfowler.com/eaaCatalog/rowDataGateway.html">Row Data
21             Gateway</ulink> Pattern implementiert.
22         </para>
23     </sect2>
25     <sect2 id="zend.db.table.concrete">
26         <title>Zend_Db_Table als konkrete Klasse verwenden</title>
28         <para>
29             Ab Zend Framework 1.9 kann man <classname>Zend_Db_Table</classname> instanziieren. Der
30             zusätzliche Vorteil ist das man die Basisklasse nicht erweitern und konfigurieren muß um
31             einfache Operationen wie auswählen, einfügen, aktualisieren und löschen in einer
32             einzelnen Tabelle durchzuführen. Anbei ist ein Beispiel der einfachsten Verwendung.
33         </para>
35         <example id="zend.db.table.defining.concrete-instantiation.example1">
36             <title>Eine Table Klasse nur mit dem Stringnamen deklarieren</title>
38                 <programlisting language="php"><![CDATA[
39 Zend_Db_Table::setDefaultAdapter($dbAdapter);
40 $bugTable = new Zend_Db_Table('bug');
41 ]]></programlisting>
42         </example>
44         <para>
45             Das obige Beispiel zeigt das einfachste Beispiel. Nicht alle der unten beschriebenen
46             Optionen sollten für die Konfiguration von <classname>Zend_Db_Table</classname> Tabellen
47             durchgeführt werden. Wenn man in der Lage sein will das konkrete Verwendungsbeispiel
48             zusätzlich zu den komplexeren Abhängigkeits Features zu verwenden sehen Sie in die
49             <classname>Zend_Db_Table_Definition</classname> Dokumentation.
50         </para>
51     </sect2>
53     <sect2 id="zend.db.table.defining">
54         <title>Definieren einer Table Klasse</title>
56         <para>
57             Für jede Tabelle der Datenbank auf die zugegriffen werden soll, sollte eine eine Klasse
58             erzeugt werden, welche <classname>Zend_Db_Table_Abstract</classname> erweitert.
59         </para>
61         <sect3 id="zend.db.table.defining.table-schema">
62             <title>Definieren des Tabellennamens und Schemas</title>
64             <para>
65                 Die Tabelle der Datenbank, für welche die Klasse bestimmt ist, wird mit der
66                 protected Variablen <varname>$_name</varname> angegeben. Es ist ein String, welcher
67                 den Namen der Tabelle enthalten muss, wie er in der Datenbank erscheint.
68             </para>
70             <example id="zend.db.table.defining.table-schema.example1">
71                 <title>Angeben einer Table Klasse mit ausdrücklichem Tabellennamen</title>
73                 <programlisting language="php"><![CDATA[
74 class Bugs extends Zend_Db_Table_Abstract
76     protected $_name = 'bugs';
78 ]]></programlisting>
79             </example>
81             <para>
82                 Wird keine Tabellenname angegeben, so wird ein Standard verwendet, welcher dem
83                 Namen der Klasse entspricht. Wird sich auf diesen Standard verlassen, so muss der
84                 Klassenname der Schreibweise der Tabelle entsprechen, wie sie in der Datenbank
85                 erscheint.
86             </para>
88             <example id="zend.db.table.defining.table-schema.example">
89                 <title>Angeben einer Table Klasse mit inbegriffenem Tabellennamen</title>
91                 <programlisting language="php"><![CDATA[
92 class bugs extends Zend_Db_Table_Abstract
94     // Tabellenname entspricht dem Klassennamen
96 ]]></programlisting>
97             </example>
99             <para>
100                 Es kann auch ein Schema für die Tabelle angegeben werden. Entweder mit der protected
101                 Variablen <varname>$_schema</varname> oder mit dem Schema vorangestellt in der
102                 <varname>$_name</varname> Eigenschaft. Jedes Schema welches in der
103                 <varname>$_name</varname> Eigenschaft angegeben ist wird vorrangig gegenüber dem
104                 Schema der <varname>$_schema</varname> Eigenschaft behandelt. In einigen
105                 <acronym>RDBMS</acronym> Marken ist die Bezeichnung für Schema "database" oder
106                 "tablespace", wird aber ähnlich verwendet.
107             </para>
109             <example id="zend.db.table.defining.table-schema.example3">
110                 <title>Angeben einer Table Klasse mit Schema</title>
112                 <programlisting language="php"><![CDATA[
113 // Erste Möglichkeit:
114 class Bugs extends Zend_Db_Table_Abstract
116     protected $_schema = 'bug_db';
117     protected $_name   = 'bugs';
120 // Zweite Möglichkeit:
121 class Bugs extends Zend_Db_Table_Abstract
123     protected $_name = 'bug_db.bugs';
126 // Wenn Schema sowohl in $_name als auch $_schema angegeben wird, so bekommt $_name vorrang:
128 class Bugs extends Zend_Db_Table_Abstract
130     protected $_name   = 'bug_db.bugs';
131     protected $_schema = 'ignored';
133 ]]></programlisting>
134             </example>
136             <para>
137                 Die Schema und Tabellennamen können auch mit Konstruktor Konfigurationsdirektiven
138                 angegeben werden, welche jegliche Standardwerte, angegeben in den
139                 <varname>$_name</varname> und <varname>$_schema</varname> Eigenschaften,
140                 überschreiben. Eine Schema Angabe welche mit der <property>name</property> Directive
141                 angegeben wurde überschreibt jeglichen Wert welcher von der
142                 <property>schema</property> Option bereitgestellt ist.
143             </para>
145             <example id="zend.db.table.defining.table-schema.example.constructor">
146                 <title>Angebend von Tabellen und Schemanamen während der Instanziierung</title>
148                 <programlisting language="php"><![CDATA[
149 class Bugs extends Zend_Db_Table_Abstract
153 // Erste Möglichkeit:
155 $tableBugs = new Bugs(array('name' => 'bugs', 'schema' => 'bug_db'));
157 // Zweite Möglichkeit:
159 $tableBugs = new Bugs(array('name' => 'bug_db.bugs'));
161 // Wenn Schema sowohl in $_name als auch $_schema angegeben wird,
162 // so bekommt $_name vorrang:
164 $tableBugs = new Bugs(array('name' => 'bug_db.bugs',
165                             'schema' => 'ignored'));
166 ]]></programlisting>
167             </example>
169             <para>
170                 Wenn kein Schemaname angegeben wird, so wird als Standard der Schemaname des
171                 Datenbankadapters verwendet.
172             </para>
173         </sect3>
175         <sect3 id="zend.db.table.defining.primary-key">
176             <title>Angeben des Primärschlüssels der Tabelle</title>
178             <para>
179                 Jede Tabelle muss einen Primärschlüssel haben. Die Spalte des Primärschlüssels kann
180                 mit der protected Variablen <varname>$_primary</varname> angegeben werden. Sie
181                 enthält entweder einen String, welcher die einzelen Spalte benennt, oder ein Array
182                 von Spaltennamen, wenn der Primärschlüssel ein zusammengesetzter Schlüssel ist.
183             </para>
185             <example id="zend.db.table.defining.primary-key.example">
186                 <title>Beispiel für das spezifizieren eines Primärschlüssels</title>
188                 <programlisting language="php"><![CDATA[
189 class Bugs extends Zend_Db_Table_Abstract
191     protected $_name = 'bugs';
192     protected $_primary = 'bug_id';
194 ]]></programlisting>
195             </example>
197             <para>
198                 Wenn kein Primärschlüssel angegeben wird, versucht
199                 <classname>Zend_Db_Table_Abstract</classname> den Primärschlüssel mit Hilfe der
200                 <methodname>describeTable()</methodname> Methode zu ermitteln.
201             </para>
203             <note>
204                 <para>
205                     Jede Table Klasse muss wissen mit welche(r/n) Spalte(n) Zeilen eindeutig
206                     identifiziert werden können. Wenn keine Primärschlüssel Spalte(n) in der
207                     Klassendefinition oder als Argument für den Konstruktor angegeben wurde und
208                     nicht aus den Metadaten der Tabelle mit Hilfe der
209                     <methodname>describeTable()</methodname> Methode ermittelt werden kann, dann
210                     kann die Tabelle nicht mit <classname>Zend_Db_Table</classname> verwendet
211                     werden.
212                 </para>
213             </note>
214         </sect3>
216         <sect3 id="zend.db.table.defining.setup">
217             <title>Überschreiben von Table Setup Methoden</title>
219             <para>
220                 Wenn eine Instanz einer Table Klasse erzeugt wird, ruft der Konstruktor einige
221                 protected Methoden auf, die Metadaten der Tabelle initialisieren. Jede dieser
222                 Methoden kann erweitert werden um Metadaten explizit anzugeben. Dabei darf nicht
223                 vergessen werden am Ende der eigenen Methode die gleichnamige Methode der
224                 Parentklasse aufzurufen.
225             </para>
227             <example id="zend.db.table.defining.setup.example">
228                 <title>Beispiel für das Überschreiben der _setupTableName() Methode</title>
230                 <programlisting language="php"><![CDATA[
231 class Bugs extends Zend_Db_Table_Abstract
233     protected function _setupTableName()
234     {
235         $this->_name = 'bugs';
236         parent::_setupTableName();
237     }
239 ]]></programlisting>
240             </example>
242             <para>
243                 Folgende Setup Methoden sind überschreibbar:
244             </para>
246             <itemizedlist>
247                 <listitem>
248                     <para>
249                         <methodname>_setupDatabaseAdapter()</methodname> überprüft ob ein Adapter
250                         bereitgestellt wird; nimmt einen Standardadapter aus der Registry, wenn
251                         benötigt. Durch das Überschreiben dieser Methode kann ein Datenbankadapter
252                         aus einer anderen Quelle gesetzt werden.
253                     </para>
254                 </listitem>
256                 <listitem>
257                     <para>
258                         <methodname>_setupTableName()</methodname> setzt den standard Tabellennamen
259                         auf den Namen der Klasse. Durch das Überschreiben dieser Methode kann der
260                         Tabellenname gesetzt werden bevor dieses Standardverhalten abläuft.
261                     </para>
262                 </listitem>
264                 <listitem>
265                     <para>
266                         <methodname>_setupMetadata()</methodname> setzt das Schema wenn der
267                         Tabellenname dem Muster "<command>schema.table</command>" entspricht; ruft
268                         <methodname>describeTable()</methodname> auf um Metadaten Informationen zu
269                         erhalten; Standardisiert das <varname>$_cols</varname> Array auf die
270                         Spalten wie von <methodname>describeTable()</methodname> geliefert. Durch
271                         das Überschreiben dieser Methode können die Spalten angegeben werden.
272                     </para>
273                 </listitem>
275                 <listitem>
276                     <para>
277                         <methodname>_setupPrimaryKey()</methodname> standardisiert die
278                         Primärschlüssel Spalten zu denen geliefert von
279                         <methodname>describeTable()</methodname>; prüft ob die Primärschlüssel
280                         Spalten im <varname>$_cols</varname> Array enthalten sind. Durch
281                         das Überschreiben dieser Methode können die Primärschlüssel Spalten
282                         angegeben werden.
283                     </para>
284                 </listitem>
285             </itemizedlist>
286         </sect3>
288         <sect3 id="zend.db.table.initialization">
289             <title>Tabellen Initialisierung</title>
291             <para>
292                 Wenn Anwendungs-spezifische Logik initialisiert werden soll wenn eine
293                 Tabellenklasse erstellt wird, kann man entscheiden die Aufgaben in die
294                 <methodname>init()</methodname> Methode zu verschieben, die aufgerufen wird nachdem
295                 alle Tabellen Metadaten bearbeitet wurden. Das ist besser als die
296                 <methodname>__construct()</methodname> Methode wenn die Metadaten nicht
297                 programmtechnisch verändert werden sollen.
298             </para>
300             <example id="zend.db.table.defining.init.usage.example">
301                 <title>Beispielverwendung der init() Methode</title>
303                 <programlisting language="php"><![CDATA[
304 class Bugs extends Zend_Db_Table_Abstract
306     protected $_observer;
308     public function init()
309     {
310         $this->_observer = new MyObserverClass();
311     }
313 ]]></programlisting>
314             </example>
315         </sect3>
316     </sect2>
318     <sect2 id="zend.db.table.constructing">
319         <title>Erzeugen einer Instanz einer Tabelle</title>
321         <para>
322             Bevor eine Table Klasse verwendet werden kann muss eine Instanz mit dem Konstruktor
323             erzeugt werden. Das Konstruktor Argument ist ein Array von Optionen. Die wichtigste
324             Option für einen Tabellenkonstruktor ist die Instanz der Adapterklasse, welche eine live
325             Verbindung zu einem <acronym>RDBMS</acronym> repräsentiert. Es gibt drei Möglichkeiten
326             den Datenbankadapter einer Tabellenklasse anzugeben und diese sind unten beschrieben:
327         </para>
329         <sect3 id="zend.db.table.constructing.adapter">
330             <title>Angeben eines Datenbankadapters</title>
332             <para>
333                 Der erste Weg einen Datenbankadapter an eine Table Klasse bereitzustellen ist, ein
334                 Objekt des Typs <classname>Zend_Db_Adapter_Abstract</classname> im Options Array,
335                 bezeichnet mit dem Schlüssel '<property>db</property>', zu übergeben.
336             </para>
338             <example id="zend.db.table.constructing.adapter.example">
339                 <title>
340                     Beispiel für das Erzeugen einer Tabelle mit Nutzung eines Adapterobjekts
341                 </title>
343                 <programlisting language="php"><![CDATA[
344 $db = Zend_Db::factory('PDO_MYSQL', $options);
346 $table = new Bugs(array('db' => $db));
347 ]]></programlisting>
348             </example>
349         </sect3>
351         <sect3 id="zend.db.table.constructing.default-adapter">
352             <title>Setzen eines Standard-Datenbankadapters</title>
354             <para>
355                 Der zweite Weg einer Table Klasse einen Datenbankadapter bereit zu stellen ist es,
356                 ein Objekt des Typs <classname>Zend_Db_Adapter_Abstract</classname> zu deklarieren
357                 und als Standard für alle nachfolgenden Instanzen von Table der Applikation zu
358                 setzen. Dies kann mit der static Methode
359                 <methodname>Zend_Db_Table_Abstract::setDefaultAdapter()</methodname> getan werden.
360                 Das Argument ist ein Objekt des Typs
361                 <classname>Zend_Db_Adapter_Abstract</classname>.
362             </para>
364             <example id="zend.db.table.constructing.default-adapter.example">
365                 <title>Beispiel für das erstellen von Table mit einem Standardadapter</title>
367                 <programlisting language="php"><![CDATA[
368 $db = Zend_Db::factory('PDO_MYSQL', $options);
369 Zend_Db_Table_Abstract::setDefaultAdapter($db);
371 // Später...
373 $table = new Bugs();
374 ]]></programlisting>
375             </example>
377             <para>
378                 Es kann geeignet sein den Datenbankadapter an einer zentralen Stelle der Anwendung,
379                 wie dem Bootstrap, zu erzeugen, und als Standardadapter zu speichern. Dies hilft
380                 sicher zu stellen, das der verwendete Adapter in der gesamten Anwendung der gleiche
381                 ist. Allerdings kann nur eine einzelne Adapterinstanz als Standardadapter verwendet
382                 werden.
383             </para>
384         </sect3>
386         <sect3 id="zend.db.table.constructing.registry">
387             <title>Speichern eines Datenbankadapters in der Registry</title>
389             <para>
390                 Der dritte Weg einer Table Klasse einen Datenbankadapter bereit zu stellen ist es
391                 einen String in dem Optionsarray zu übergeben, auch mit dem
392                 '<property>db</property>' Schlüssel identifiziert. Der String wird als Schlüssel der
393                 statischen <classname>Zend_Registry</classname> Instanz verwendet, wo der Eintrag
394                 mit dem Schlüssel ein Objekt des Typs
395                 <classname>Zend_Db_Adapter_Abstract</classname> ist.
396             </para>
398             <example id="zend.db.table.constructing.registry.example">
399                 <title>Beispiel für das Erzeugen von Table mit einem Registry Schlüssel</title>
401                 <programlisting language="php"><![CDATA[
402 $db = Zend_Db::factory('PDO_MYSQL', $options);
403 Zend_Registry::set('my_db', $db);
405 // Später...
407 $table = new Bugs(array('db' => 'my_db'));
408 ]]></programlisting>
409             </example>
411             <para>
412                 Wie das Setzen eines Standardadapters, bietet auch dieses sicher zu stellen das die
413                 gleiche Adapter Instanz in der gesamten Anwendung verwendet wird. Nutzen der
414                 Registry ist flexibler, da mehr als eine Adapterinstanz gepeichert werden kann. Eine
415                 angegebene Adapterinstanz ist spezifisch für eine bestimmte <acronym>RDBMS</acronym>
416                 Marke und Datenbankinstanz. Wenn die Anwendung Zugriff auf mehrere Datenbanken
417                 benötigt oder auch mehrere Datenbank Marken, dann müssen mehrere Adapter verwendet
418                 werden.
419             </para>
420         </sect3>
421     </sect2>
423     <sect2 id="zend.db.table.insert">
424         <title>Zeilen in eine Tabelle einfügen</title>
426         <para>
427             Table Objekte können verwendet werden um Zeilen in die Datenbank Tabelle einzufügen auf
428             der das Table Objekt basiert. Hierzu kann die <methodname>insert()</methodname> Methode
429             des Table Objektes verwendet werden. Das Argument ist ein assoziatives Array, das
430             Spalten Namen mit Werten verbindet.
431         </para>
433         <example id="zend.db.table.insert.example">
434             <title>Beispiel für das Einfügen in eine Tabelle</title>
436             <programlisting language="php"><![CDATA[
437 $table = new Bugs();
439 $data = array(
440     'created_on'      => '2007-03-22',
441     'bug_description' => 'Irgendwas falsch',
442     'bug_status'      => 'NEW'
445 $table->insert($data);
446 ]]></programlisting>
447         </example>
449         <para>
450             Standardmäßig werden Werte im Daten Array als literale Werte eingefügt durch das
451             Verwenden von Parametern. Wenn es notwendig ist das diese als <acronym>SQL</acronym>
452             Ausdruck behandelt werden, muß sichergestellt werden das Sie sich von reinen Strings
453             unterscheiden. Es kann ein Objekt vom Typ <classname>Zend_Db_Expr</classname> verwendet
454             werden um das zu bewerkstelligen.
455         </para>
457         <example id="zend.db.table.insert.example-expr">
458             <title>Beispiel für das Einfügen von Ausdrücken in einer Tabelle</title>
460             <programlisting language="php"><![CDATA[
461 $table = new Bugs();
463 $data = array(
464     'created_on'      => new Zend_Db_Expr('CURDATE()'),
465     'bug_description' => 'Irgendwas ist falsch',
466     'bug_status'      => 'NEU'
468 ]]></programlisting>
469         </example>
471         <para>
472             Um obigen Beispiel vom Einfügen von Zeilen, wird angenommen das die Tabelle einen
473             automatischen Primärschlüssel hat. Das ist das Standardverhalten von
474             <classname>Zend_Db_Table_Abstract</classname>, aber es gibt auch andere Typen von
475             Primärschlüssel. Das folgende Kapitel beschreibt wie verschiedene Typen von
476             Primärschlüssel unterstützt werden.
477         </para>
479         <sect3 id="zend.db.table.insert.key-auto">
480             <title>Eine Tabelle mit einem automatischen Primärschlüssel verwenden</title>
482             <para>
483                 Ein automatischer Primärschlüssel erzeigt einen eindeutigen Integerwert wenn die
484                 Spalte des Primären Typs in der eigenen <acronym>SQL</acronym>
485                 <constant>INSERT</constant> Anweisung unterdrückt wird.
486             </para>
488             <para>
489                 Wenn die geschützte Variable <varname>$_sequence</varname>, in
490                 <classname>Zend_Db_Table_Abstract</classname>, als boolscher Wert
491                 <constant>TRUE</constant> definiert wird, nimmt die Klasse an das die Tabelle einen
492                 automatischen Primärschlüssel hat.
493             </para>
495             <example id="zend.db.table.insert.key-auto.example">
496                 <title>
497                     Beispiel für das Deklarierens einer Tabelle mit einem automatischen
498                     Primärschlüssel
499                 </title>
501                 <programlisting language="php"><![CDATA[
502 class Bugs extends Zend_Db_Table_Abstract
504     protected $_name = 'bugs';
506     // Das ist der Standardwert in der Zend_Db_Table_Abstract Klasse;
507     // er muß nicht definiert werden.
508     protected $_sequence = true;
510 ]]></programlisting>
511             </example>
513             <para>
514                 MySQL, Microsoft <acronym>SQL</acronym> Server, und SQLite sind Beispiele von
515                 <acronym>RDBMS</acronym> Marken die automatische Primärschlüssel unterstützen.
516             </para>
518             <para>
519                 PostgreSQL hat eine <constant>SERIAL</constant> Notation die implizit eine Sequenz
520                 definiert die auf den Tabellen- und Spaltennamen basiert, und diese Sequenz
521                 verwendet, um einen Schlüsselwert für neue Zeilen zu erstellen.
522                 <acronym>IBM</acronym> <acronym>DB2</acronym> hat eine
523                 <constant>IDENTITY</constant> Notation die ähnlich arbeitet. Wenn eine dieser
524                 Notationen verwendet wird, muß der <classname>Zend_Db_Table</classname> Klasse
525                 mitgeteilt werden das Sie eine automatische Spalte hat, indem
526                 <varname>$_sequence</varname> auf <constant>TRUE</constant> gesetzt wird.
527             </para>
528         </sect3>
530         <sect3 id="zend.db.table.insert.key-sequence">
531             <title>Eine Tabelle mit einer Sequenz verwenden</title>
533             <para>
534                 Eine Sequenz ist ein Datenbank Objekt das einen eindeutigen Wert erstellt, der als
535                 Wert des Primärschlüssels in einer oder mehreren Tabellen der Datenbank verwendet
536                 werden kann.
537             </para>
539             <para>
540                 Wenn <varname>$_sequence</varname> als String definiert wird, nimmt
541                 <classname>Zend_Db_Table_Abstract</classname> an das der String den Namen des
542                 Sequenz Objektes in der Datenbank benennt. Die Sequenz wird aufgerufen um einen
543                 neuen Wert zu erstellen, und dieser Wert wird in der <constant>INSERT</constant>
544                 Operation verwendet.
545             </para>
547             <example id="zend.db.table.insert.key-sequence.example">
548                 <title>Beispiel für das Deklaration einer Tabelle mit einer Sequenz</title>
550                 <programlisting language="php"><![CDATA[
551 class Bugs extends Zend_Db_Table_Abstract
553     protected $_name = 'bugs';
555     protected $_sequence = 'bug_sequence';
557 ]]></programlisting>
558             </example>
560             <para>
561                 Oracle, PostgreSQL, und <acronym>IBM</acronym> <acronym>DB2</acronym> sind Beispiele
562                 von <acronym>RDBMS</acronym> Marken die Sequenz Objekte in der Datenbank
563                 unterstützen.
564             </para>
566             <para>
567                 PostgreSQL und <acronym>IBM</acronym> <acronym>DB2</acronym> haben auch einen Syntax
568                 der Sequenzen implizit definiert und diese mit Spalten assoziiert. Wenn diese
569                 Notation verwendet wird, muß der Tabelle gesagt werden das Sie eine automatische
570                 Schlüsselspalte besitzt. Der Name der Sequenz muß nur in den Fällen als String
571                 definiert werden in denen die Sequenz explizit aufgerufen wird um den nächsten
572                 Schlüsselwert zu erhalten.
573             </para>
574         </sect3>
576         <sect3 id="zend.db.table.insert.key-natural">
577             <title>Eine Tabelle mit einem natürlichen Schlüssel verwenden</title>
579             <para>
580                 Einige Tabellen haben natürliche Schlüssel. Das bedeutet das der Schlüssel nicht
581                 automatisch durch die Tabelle oder eine Sequenz erstellt wird. Der Wert für den
582                 Primärschlüssel muß in diesem Fall selbst definiert werden.
583             </para>
585             <para>
586                 Wenn <varname>$_sequence</varname> als boolsches <constant>FALSE</constant>
587                 definiert wird, nimmt <classname>Zend_Db_Table_Abstract</classname> an das die
588                 Tabelle einen natürlichen Primärschlüssel hat. Es müssen Werte für die Spalte des
589                 Primärschlüssels im Array der Daten definiert werden die an die
590                 <methodname>insert()</methodname> Methode übergeben werden, andernfalls wird diese
591                 Methode eine <classname>Zend_Db_Table_Exception</classname> werfen.
592             </para>
594             <example id="zend.db.table.insert.key-natural.example">
595                 <title>
596                     Beispiel für das Definieren einer Tabelle mit einem natürlichen Schlüssel
597                 </title>
599                 <programlisting language="php"><![CDATA[
600 class BugStatus extends Zend_Db_Table_Abstract
602     protected $_name = 'bug_status';
604     protected $_sequence = false;
606 ]]></programlisting>
607             </example>
609             <note>
610                 <para>
611                     Alle <acronym>RDBMS</acronym> Marken unterstützen Tabellen mit natürlichen
612                     Schlüsseln. Beispiele von Tabellen die oft so definiert werden das Sie
613                     natürliche Schlüssel besitzen sind Lookup Tabellen, Durchschnitts Tabellen in
614                     viele-zu-viele Beziehungen, oder die meisten Tabellen mit komponierten
615                     Primärschlüsseln.
616                 </para>
617             </note>
618         </sect3>
619     </sect2>
621     <sect2 id="zend.db.table.update">
622         <title>Zeilen in einer Tabelle aktualisieren</title>
624         <para>
625             Spalten können in der Datenbanktabelle aktualisiert werden indem die
626             <methodname>update()</methodname> Methode der Table Klasse verwendet wird. Diese Methode
627             nimmt zwei Argumente: ein assoziatives Array von Spalten die geändert werden sollen und
628             neue Werte die diesen Spalten hinzugefügt werden; und einen <acronym>SQL</acronym>
629             Ausdruck der in der <constant>WHERE</constant> Klausel verwendet wird, als Kriterium für
630             die Zeilen die in der <constant>UPDATE</constant> Operation geändert werden sollen.
631         </para>
633         <example id="zend.db.table.update.example">
634             <title>Beispiel für das Aktualisieren von Zeilen in einer Tabelle</title>
636             <programlisting language="php"><![CDATA[
637 $table = new Bugs();
639 $data = array(
640     'updated_on'      => '2007-03-23',
641     'bug_status'      => 'FIXED'
644 $where = $table->getAdapter()->quoteInto('bug_id = ?', 1234);
646 $table->update($data, $where);
647 ]]></programlisting>
648         </example>
650         <para>
651             Da die <methodname>update()</methodname> Methode der Tabelle zur
652             <link linkend="zend.db.adapter.write.update"><methodname>update()</methodname></link>
653             Methode des Datenbank Adapters weiterleitet, kann das zweite Argument ein Array von
654             <acronym>SQL</acronym> Ausdrücken sein. Diese Ausdrücke werden als Boolsche Terme
655             kombiniert indem ein <constant>AND</constant> Operator verwendet wird.
656         </para>
658         <note>
659             <para>
660                 Die Werte und Identifizierer im <acronym>SQL</acronym> Ausdruck werden nicht in
661                 Anführungszeichen gesetzt. Wenn Werte oder Identifizierer vorhanden sind die das
662                 Setzen in Anführungszeichen benötigen, ist man selbst dafür zuständig das dies getan
663                 wird. Die <methodname>quote()</methodname>, <methodname>quoteInto()</methodname> und
664                 <methodname>quoteIdentifier()</methodname> Methoden des Datenbank Adapters können
665                 dafür verwendet werden.
666             </para>
667         </note>
668     </sect2>
670     <sect2 id="zend.db.table.delete">
671         <title>Zeilen aus einer Tabelle löschen</title>
673         <para>
674             Zeilen können von einer Datenbanktabelle gelöscht werden indem die
675             <methodname>delete()</methodname> Methode verwendet wird. Diese Methode nimmt ein
676             Argument, welches ein <acronym>SQL</acronym> Ausdruck ist, der in der
677             <constant>WHERE</constant> Klausel als Kriterium dafür verwendet wird, welche Zeilen
678             gelöscht werden sollen.
679         </para>
681         <example id="zend.db.table.delete.example">
682             <title>Beispiel für das Löschen von Zeilen einer Tabelle</title>
684             <programlisting language="php"><![CDATA[
685 $table = new Bugs();
687 $where = $table->getAdapter()->quoteInto('bug_id = ?', 1235);
689 $table->delete($where);
690 ]]></programlisting>
691         </example>
693         <para>
694             Da die <methodname>delete()</methodname> Methode der Tabelle zur
695             <link linkend="zend.db.adapter.write.delete"><methodname>delete()</methodname></link>
696             Methode des Datenbank Adapters weiterleitet, kann das Argument ein Array von
697             <acronym>SQL</acronym> Ausdrücken sein. Diese Ausdrücke werden als boolsche Terme
698             kombiniert indem ein <constant>AND</constant> Operator verwendet wird.
699         </para>
701         <note>
702             <para>
703                 Die Werte und Identifizierer im <acronym>SQL</acronym> Ausdruck werden nicht in
704                 Anführungszeichen gesetzt. Wenn Werte oder Identifizierer vorhanden sind die das
705                 Setzen in Anführungszeichen benötigen, ist man selbst dafür zuständig das dies getan
706                 wird. Die <methodname>quote()</methodname>, <methodname>quoteInto()</methodname> und
707                 <methodname>quoteIdentifier()</methodname> Methoden des Datenbank Adapters können
708                 dafür verwendet werden.
709             </para>
710         </note>
711     </sect2>
713     <sect2 id="zend.db.table.find">
714         <title>Zeilen durch den Primärschlüssel finden</title>
716         <para>
717             Die Datenbanktabelle kann nach passenden Zeilen für spezifizierte Werte im
718             Primärschlüssel abgefragt werden, indem die <methodname>find()</methodname> Methode
719             verwendet wird. Das erste Argument dieser Methode ist entweder ein einzelner Wert oder
720             ein Array von Werten die dem Primärschlüssel dieser Tabelle entsprechen.
721         </para>
723         <example id="zend.db.table.find.example">
724             <title>Beispiel für das Finden von Zeilen durch Werte des Primärschlüssels</title>
726             <programlisting language="php"><![CDATA[
727 $table = new Bugs();
729 // Eine einzelne Zeile finden
730 // Gibt ein Rowset zurück
731 $rows = $table->find(1234);
733 // Mehrere Zeilen finden
734 // Gibt auch ein Rowset zurück
735 $rows = $table->find(array(1234, 5678));
736 ]]></programlisting>
737         </example>
739         <para>
740             Wenn ein einzelner Wert spezifiziert wird, gibt die Methode auch maximal eine Zeile
741             zurück, weil ein Primärschlüssel keinen doppelten Wert haben kann und es maximal eine
742             Zeile in der Datenbank gibt die dem spezifizierten Wert entspricht. Wenn mehrere Werte
743             in einem Array spezifiziert werden, gibt die Methode maximal soviele Zeilen zurück wie
744             die Anzahl an unterschiedlichen Werten die spezifiziert wurden.
745         </para>
747         <para>
748             Die <methodname>find()</methodname> Methode kann weniger Zeilen zurückgeben als die
749             Anzahl an Werten die für den Primärschlüssel definiert wurden, wenn einige der Werte
750             keiner Zeile in der Datenbank Tabelle entsprechen. Die Methode kann sogar null Zeilen
751             zurückgeben. Weil die Anzahl an zurückgegebenen Zeilen variabel ist, gibt die
752             <methodname>find()</methodname> Methode ein Objekt vom Typ
753             <classname>Zend_Db_Table_Rowset_Abstract</classname> zurück.
754         </para>
756         <para>
757             Wenn der Primärschlüssel ein komponierter Schlüssel ist, als einer der aus mehreren
758             Spalten besteht, können die zusätzlichen Spalten als zusätzliche Argumente in der
759             <methodname>find()</methodname> Methode definiert werden. Es müssen soviele Argumente
760             angegeben werden wie Spalten im Primärschlüssel der Tabelle existieren.
761         </para>
763         <para>
764             Um mehrere Zeilen von einer Tabelle mit einem kombinierten Primärschlüssel zu finden,
765             muß ein Array für jedes der Argumente übergeben werden. Alle dieser Arrays müssen die
766             gleiche Anzahl an Elementen haben. Die Werte in jedem Array werden in Tupeln geformt und
767             gereiht; zum Beispiel definiert das erste Element in allen Array Argumenten den ersten
768             kombinierten Wert des Primärschlüssels, das zweite Element von allen Arrays definiert
769             den zweiten kombinierten Wert des Primärschlüssels, und so weiter.
770         </para>
772         <example id="zend.db.table.find.example-compound">
773             <title>
774                 Beispiel für das Finden von Zeilen durch Werte von kombinierten Primärschlüsseln
775             </title>
777             <para>
778                 Der Aufruf von <methodname>find()</methodname> anbei um mehreren Zeilen zu
779                 entsprechen kann zwei Zeilen in der Datenbank entsprechen. Die erste Zeile muß den
780                 Wert des Primärenschlüssels (1234, 'ABC') haben, und die zweite Zeile den Wert des
781                 Primärschlüssels (5678, 'DEF').
782             </para>
784             <programlisting language="php"><![CDATA[
785 class BugsProducts extends Zend_Db_Table_Abstract
787     protected $_name = 'bugs_products';
788     protected $_primary = array('bug_id', 'product_id');
791 $table = new BugsProducts();
793 // Eine einzelne Zeilen mit einem kombinierten Primärschlüssel finden
794 // Gibt ein Rowset zurück
795 $rows = $table->find(1234, 'ABC');
797 // Mehrere Zeilen mit einem kombinierten Primärschlüssel finden
798 // Gibt auch ein Rowset zurück
799 $rows = $table->find(array(1234, 5678), array('ABC', 'DEF'));
800 ]]></programlisting>
801         </example>
802     </sect2>
804     <sect2 id="zend.db.table.fetch-all">
805         <title>Ein Set von Zeilen abfragen</title>
807         <sect3 id="zend.db.table.fetch-all.select">
808             <title>Select API</title>
810             <warning>
811                 <para>
812                     Die <acronym>API</acronym> für die Hol-Operationen wurde ausgeweitet um
813                     einem <classname>Zend_Db_Table_Select</classname> Objekt zu erlauben die
814                     Abfrage zu modifizieren. Trotzdem wird die veraltete Verwendung der
815                     <methodname>fetchRow()</methodname> und <methodname>fetchAll()</methodname>
816                     Methoden weiterhin ohne Änderungen funktionieren.
817                 </para>
819                 <para>
820                     Die folgenden Ausdrücke sind gültig und funktionell identisch, trotzdem wird
821                     empfohlen den Code zu aktualisieren um Vorteil aus der neuen Verwendung zu
822                     ziehen wo das möglich ist.
823                 </para>
825                 <programlisting language="php"><![CDATA[
827  * Ein Rowset holen
828  */
829 $rows = $table->fetchAll(
830     'bug_status = "NEW"',
831     'bug_id ASC',
832     10,
833     0
834     );
835 $rows = $table->fetchAll(
836     $table->select()
837         ->where('bug_status = ?', 'NEW')
838         ->order('bug_id ASC')
839         ->limit(10, 0)
840     );
841 // oder mit Bindung
842 $rows = $table->fetchAll(
843     $table->select()
844         ->where('bug_status = :status')
845         ->bind(array(':status'=>'NEW')
846         ->order('bug_id ASC')
847         ->limit(10, 0)
848     );
851  * Eine einzelne Zeile holen
852  */
853 $row = $table->fetchRow(
854     'bug_status = "NEW"',
855     'bug_id ASC'
856     );
857 $row = $table->fetchRow(
858     $table->select()
859         ->where('bug_status = ?', 'NEW')
860         ->order('bug_id ASC')
861     );
862 // oder mit Bindung
863 $row = $table->fetchRow(
864     $table->select()
865         ->where('bug_status = :status')
866         ->bind(array(':status'=>'NEW')
867         ->order('bug_id ASC')
868     );
869 ]]></programlisting>
870             </warning>
872             <para>
873                 Das <classname>Zend_Db_Table_Select</classname> Objekt ist eine Erweiterung des
874                 <classname>Zend_Db_Select</classname> Objekts das spezielle Einschränkungen zu einer
875                 Abfrage hinzufügt. Die Verbesserungen und Einschränkungen sind folgende:
876             </para>
878             <itemizedlist>
879                 <listitem>
880                     <para>
881                         Man <emphasis>kann</emphasis> sich entscheiden ein Subset von Zeilen einer
882                         fetchRow oder fetchAll Abfrage zurückzuerhalten. Dann kann Vorteile durch
883                         Optimierung bieten, wenn die Rückgabe eines großes Sets an Ergebnissen für
884                         alle Zeilen nicht gewünscht wird.
885                     </para>
886                 </listitem>
888                 <listitem>
889                     <para>
890                         Man <emphasis>kann</emphasis> Zeilen spezifizieren die Ausdrücke innerhalb
891                         der ausgewählten Tabelle evaluieren. Trotzdem bedeutet das, das die
892                         zurückgegebene Zeile oder Zeilenset <property>readOnly</property> (nur
893                         lesbar) ist und nicht für <methodname>save()</methodname> Operationen
894                         verwendet werden kann. Eine <classname>Zend_Db_Table_Row</classname> mit
895                         <property>readOnly</property> Status wird eine Exception werfen wenn eine
896                         <methodname>save()</methodname> Operation versucht wird.
897                     </para>
898                 </listitem>
900                 <listitem>
901                     <para>
902                         Man <emphasis>kann</emphasis> <constant>JOIN</constant> Klauseln auf einer
903                         Auswahl erlauben um Mehrfach-Tabellen Lookups zu erlauben.
904                     </para>
905                 </listitem>
907                 <listitem>
908                     <para>
909                         Man <emphasis>kann keine</emphasis> Spalten von einer geJOINten Tabelle
910                         spezifizieren damit Sie in einer Zeile oder Zeilenset zurückgegeben werden.
911                         Wenn das versucht wird, wird ein <acronym>PHP</acronym> Fehler getriggert.
912                         Das wurde getan um Sicherzustellen das die Integrität von
913                         <classname>Zend_Db_Table</classname> gewahrt bleibt. z.B. ein
914                         <classname>Zend_Db_Table_Row</classname> sollte nur Spalten referenzieren
915                         die von seiner Elterntabelle abgeleitet sind.
916                     </para>
917                 </listitem>
918             </itemizedlist>
920             <example id="zend.db.table.qry.rows.set.simple.usage.example">
921                 <title>Einfache Verwendung</title>
923                 <programlisting language="php"><![CDATA[
924 $table = new Bugs();
926 $select = $table->select();
927 $select->where('bug_status = ?', 'NEW');
929 $rows = $table->fetchAll($select);
930 ]]></programlisting>
931             </example>
933             <para>
934                 Flüssige Interfaces sind über alle Komponenten hinweg implementiert, sodass dies zu
935                 einer abgekürzteren Form umgeschrieben werden kann.
936             </para>
938             <example id="zend.db.table.qry.rows.set.fluent.interface.example">
939                 <title>Beispiel des Fluent Interfaces</title>
941                 <programlisting language="php"><![CDATA[
942 $table = new Bugs();
944 $rows =
945     $table->fetchAll($table->select()->where('bug_status = ?', 'NEW'));
946 ]]></programlisting>
947             </example>
948         </sect3>
950         <sect3 id="zend.db.table.fetch-all.usage">
951             <title>Ein Set von Zeilen abfragen</title>
953             <para>
954                 Ein Set von Zeilen kann abgefragt werden indem irgendein Kriterium verwendet wird,
955                 das anders als die Werte des Primärschlüssels sind, indem die
956                 <methodname>fetchAll()</methodname> Methode der Tabellen Klasse verwendet wird.
957                 Diese Methode gibt ein Objekt vom Typ
958                 <classname>Zend_Db_Table_Rowset_Abstract</classname> zurück.
959             </para>
961             <example id="zend.db.table.qry.rows.set.finding.row.example">
962                 <title>Beispiel für das Finden von Zeilen durch einen Ausdruck</title>
964                 <programlisting language="php"><![CDATA[
965 $table = new Bugs();
967 $select = $table->select()->where('bug_status = ?', 'NEW');
969 $rows = $table->fetchAll($select);
970 ]]></programlisting>
971             </example>
973             <para>
974                 Der <constant>ORDER</constant> BY kann auch ein Sortier-Kriterium übergeben werden,
975                 genauso wie auch Count und Offset Integer Werte, verwendet werden können damit die
976                 Abfrage ein spezielles Subset von Zeilen zurück gibt. Diese Werte werden in einer
977                 <constant>LIMIT</constant> Klausel verwendet oder in einer ähnlichen Logik für
978                 <acronym>RDBMS</acronym> Marken welche die <constant>LIMIT</constant> Syntax nicht
979                 unterstützen.
980             </para>
982             <example id="zend.db.table.fetch-all.example2">
983                 <title>Beispiel für das Finden von Zeilen durch einen Ausdruck</title>
985                 <programlisting language="php"><![CDATA[
986 $table = new Bugs();
988 $order  = 'bug_id';
990 // Gibt die Zeilen 21 bis 30 zurück
991 $count  = 10;
992 $offset = 20;
994 $select = $table->select()->where('bug_status = ?' => 'NEW')
995                           ->order($order)
996                           ->limit($count, $offset);
998 $rows = $table->fetchAll($select);
999 ]]></programlisting>
1000             </example>
1002             <para>
1003                 Alle diese Argumente sind optional. Wenn die <constant>ORDER</constant> Klausel
1004                 unterdrückt wird, dann enthält das Ergebnis die Zeilen der Tabelle in einer
1005                 unvorhersagbaren Reihenfolge. Wenn keine <constant>LIMIT</constant> Klausel gesetzt
1006                 ist, dann wird jede Zeile dieser Tabelle zurückgegeben die der
1007                 <constant>WHERE</constant> Klausen entspricht.
1008             </para>
1009         </sect3>
1011         <sect3 id="zend.db.table.advanced.usage">
1012             <title>Fortgeschrittene Verwendung</title>
1014             <para>
1015                 Für speziellere und optimierte Ergebnisse, kann es gewünscht sein die Anzahl der
1016                 zurückgegebenen Zeilen oder Sets zu limitieren. Das kann durch die Übergabe einer
1017                 <constant>FROM</constant> Klausel an das Select Objekt getan werden. Das erste
1018                 Argument in der <constant>FROM</constant> Klausel ist identisch mit den des
1019                 <classname>Zend_Db_Select</classname> Objekts wobei man zusätzlich eine Instanz von
1020                 <classname>Zend_Db_Table_Abstract</classname> übergeben und damit den Tabellen Namen
1021                 automatisch ermitteln lassen kann.
1022             </para>
1024             <example id="zend.db.table.qry.rows.set.retrieving.a.example">
1025                 <title>Spezielle Spalten erhalten</title>
1027                 <programlisting language="php"><![CDATA[
1028 $table = new Bugs();
1030 $select = $table->select();
1031 $select->from($table, array('bug_id', 'bug_description'))
1032        ->where('bug_status = ?', 'NEW');
1034 $rows = $table->fetchAll($select);
1035 ]]></programlisting>
1036             </example>
1038             <important>
1039                 <para>
1040                     Das Rowset enthält Zeilen die trotzdem 'gültig' sind - sie enthalten bloß
1041                     ein Subset der Spalten einer Tabelle. Wenn eine <methodname>save()</methodname>
1042                     Methode auf dem Teil einer Zeile aufgerufen wird dann werden nur die vorhandenen
1043                     Felder geändert.
1044                 </para>
1045             </important>
1047             <para>
1048                 Es können Ausdrücke in einer <constant>FROM</constant> Klausel spezifiziert werden
1049                 die dann als readOnly Zeile oder Set zurückgegeben werden. In diesem Beispiel werden
1050                 Zeilen von der Bugs Tabelle zurückgegeben die einen Bereich von Nummern neuer Bugs
1051                 zeigen die von Individuen mitgeteilt wurden. Die <constant>GROUP</constant> Klausel
1052                 ist zu beachten. Die 'count' Spalte wird der Zeile für Evaluation angefügt und es
1053                 kann auch Sie zugegriffen werden wie wenn Sie ein Teil des Schemas wäre.
1054             </para>
1056             <example id="zend.db.table.qry.rows.set.retrieving.b.example">
1057                 <title>Ausdrücke als Spalten erhalten</title>
1059                 <programlisting language="php"><![CDATA[
1060 $table = new Bugs();
1062 $select = $table->select();
1063 $select->from($table,
1064               array('COUNT(reported_by) as `count`', 'reported_by'))
1065        ->where('bug_status = ?', 'NEW')
1066        ->group('reported_by');
1068 $rows = $table->fetchAll($select);
1069 ]]></programlisting>
1070             </example>
1072             <para>
1073                 Es kann auch ein Lookup als Teil der Abfrage verwendet werden um die Fetch
1074                 Operation zu verfeinern. In diesem Beispiel wird die Accounts Tabelle als Teil
1075                 einer Suche nach allen Bugs die von 'Bob' gemeldet wurden, abgefragt.
1076             </para>
1078             <example id="zend.db.table.qry.rows.set.refine.example">
1079                 <title>Beispiel für das Finden von Zeilen durch einen Ausdruck</title>
1081                 <programlisting language="php"><![CDATA[
1082 $table = new Bugs();
1084 // Bei gesetztem From Abschnitt empfangen, wichtig wenn gejoint werden soll
1085 $select = $table->select(Zend_Db_Table::SELECT_WITH_FROM_PART);
1086 $select->setIntegrityCheck(false)
1087        ->where('bug_status = ?', 'NEW')
1088        ->join('accounts', 'accounts.account_name = bugs.reported_by')
1089        ->where('accounts.account_name = ?', 'Bob');
1091 $rows = $table->fetchAll($select);
1092 ]]></programlisting>
1093             </example>
1095             <para>
1096                 <classname>Zend_Db_Table_Select</classname> wird primär verwendet um zu verbinden
1097                 und zu prüfen um die Kriterien für einen legalen <constant>SELECT</constant> Query
1098                 sicherzustellen. Trotzdem gibt es viele Fälle in denen man die Flexibilität der
1099                 <classname>Zend_Db_Table_Row</classname> benötigt und Zeilen nicht geschrieben oder
1100                 gelöscht werden müssen. Für diesen speziellen Fall ist es möglich Zeilen/-sets durch
1101                 die Übergabe eines <constant>FALSE</constant> Wertes an
1102                 <methodname>setIntegrityCheck()</methodname> zu erhalten. Das resultierende Zeilen
1103                 oder Zeilenset wird als eine 'locked' Zeile zurückgegeben (das bedeutet das
1104                 <methodname>save()</methodname>, <methodname>delete()</methodname> und jede andere
1105                 Methode die Felder setzt wird eine Ausnahme werfen).
1106             </para>
1108             <example id="zend.db.table.qry.rows.set.integrity.example">
1109                 <title>
1110                     Entfernen des Integritäts Checks von Zend_Db_Table_Select um geJOINte Zeilen zu
1111                     erlauben
1112                 </title>
1114                 <programlisting language="php"><![CDATA[
1115 $table = new Bugs();
1117 $select = $table->select(Zend_Db_Table::SELECT_WITH_FROM_PART)
1118                 ->setIntegrityCheck(false);
1119 $select->where('bug_status = ?', 'NEW')
1120        ->join('accounts',
1121               'accounts.account_name= bugs.reported_by',
1122               'account_name')
1123        ->where('accounts.account_name = ?', 'Bob');
1125 $rows = $table->fetchAll($select);
1126 ]]></programlisting>
1127             </example>
1128         </sect3>
1129     </sect2>
1131     <sect2 id="zend.db.table.fetch-row">
1132         <title>Eine einzelne Zeilen abfragen</title>
1134         <para>
1135             Eine einzelne Zeile kann abgefragt werden indem Kriterien verwendet werden die ähnlich
1136             denen der <methodname>fetchAll()</methodname> Methode sind.
1137         </para>
1139         <example id="zend.db.table.fetch-row.example1">
1140             <title>Beispiel für das Finden einer einzelnen Zeilen durch einen Ausdruck</title>
1142             <programlisting language="php"><![CDATA[
1143 $table = new Bugs();
1145 $select  = $table->select()->where('bug_status = ?', 'NEW')
1146                            ->order('bug_id');
1148 $row = $table->fetchRow($select);
1149 ]]></programlisting>
1150         </example>
1152         <para>
1153             Diese Methode gibt ein Objekt vom Typ <classname>Zend_Db_Table_Row_Abstract</classname>
1154             zurück. Wenn die spezifizierten Sortier-Kriterien keiner Zeile in der Datenbank Tabelle
1155             entsprechen gibt <methodname>fetchRow()</methodname> <acronym>PHP</acronym>'s
1156             <constant>NULL</constant> Wert zurück.
1157         </para>
1158     </sect2>
1160     <sect2 id="zend.db.table.info">
1161         <title>Informationen der Tabellen Metadaten erhalten</title>
1163         <para>
1164             Die <classname>Zend_Db_Table_Abstract</classname> Klasse bietet einige Informationen
1165             über Ihre Metadaten. Die <methodname>info()</methodname> Methode gibt eine Array
1166             Struktur mit Informationen über die Tabelle, Ihre Spalten und Primärschlüssel zurück,
1167             sowie andere Metadaten.
1168         </para>
1170         <example id="zend.db.table.info.example">
1171             <title>Beispiel für das Erhalten des Namens einer Tabelle</title>
1173             <programlisting language="php"><![CDATA[
1174 $table = new Bugs();
1176 $info = $table->info();
1178 echo "Der Name der Tabelle ist " . $info['name'] . "\n";
1179 ]]></programlisting>
1180         </example>
1182         <para>
1183             Die Schlüssel des Arrays das von der <methodname>info()</methodname> Methode
1184             zurückgegeben wird sind anbei beschrieben:
1185         </para>
1187         <itemizedlist>
1188             <listitem>
1189                 <para>
1190                     <emphasis>name</emphasis> => der Name der Tabelle.
1191                 </para>
1192             </listitem>
1194             <listitem>
1195                 <para>
1196                     <emphasis>cols</emphasis> => ein Array das die Spalte(n) der Tabelle benennt.
1197                 </para>
1198             </listitem>
1200             <listitem>
1201                 <para>
1202                     <emphasis>primary</emphasis> => ein Array das die Spalte(n) des Primärschlüssels
1203                     benennt.
1204                 </para>
1205             </listitem>
1207             <listitem>
1208                 <para>
1209                     <emphasis>metadata</emphasis> => ein assoziatives Array das die Spaltennamen
1210                     mit Informationen über die Spalten zusammenführt. Das ist die Information die
1211                     durch die <methodname>describeTable()</methodname> Methode zurückgegeben wird.
1212                 </para>
1213             </listitem>
1215             <listitem>
1216                 <para>
1217                     <emphasis>rowClass</emphasis> => der Name der konkreten Klasse die für
1218                     Zeilen Objekte verwendet wird und von den Methoden dieser Table Instanz
1219                     zurückgegeben wird. Der Standardwert ist
1220                     <classname>Zend_Db_Table_Row</classname>.
1221                 </para>
1222             </listitem>
1224             <listitem>
1225                 <para>
1226                     <emphasis>rowsetClass</emphasis> => Name der konkreten Klasse für für Rowset
1227                     Objekte verwendet wird und von den Methoden dieser Table Instanz zurückgegeben
1228                     wird. Der Standardwert ist <classname>Zend_Db_Table_Rowset</classname>.
1229                 </para>
1230             </listitem>
1232             <listitem>
1233                 <para>
1234                     <emphasis>referenceMap</emphasis> => ist ein assoziatives Array von
1235                     Klassennamen von Tabellen die diese Tabelle referenzieren. Siehe
1236                     <link linkend="zend.db.table.relationships.defining">dieses Kapitel</link>.
1237                 </para>
1238             </listitem>
1240             <listitem>
1241                 <para>
1242                     <emphasis>dependentTables</emphasis> => ein Array von Klassennamen von
1243                     Tabellen die diese Tabelle referenzieren. Siehe
1244                     <link linkend="zend.db.table.relationships.defining">dieses Kapitel</link>.
1245                 </para>
1246             </listitem>
1248             <listitem>
1249                 <para>
1250                     <emphasis>schema</emphasis> => der Name des Schemas (oder der
1251                     Datenbank oder dem Tabellenraum) für diese Tabelle.
1252                 </para>
1253             </listitem>
1254         </itemizedlist>
1255     </sect2>
1257     <sect2 id="zend.db.table.metadata.caching">
1258         <title>Tabellen Metadaten cachen</title>
1260         <para>
1261             Standardmäßig fragt <classname>Zend_Db_Table_Abstract</classname> die darunterliegende
1262             Datenbank für die <link linkend="zend.db.table.info">Metadaten der Tabelle</link> ab
1263             immer wenn diese diese Daten benötigt werden um Tabellenoperationen durchzuführen. Das
1264             Tableobjekt holt die Metadaten der Tabelle von der Datenbank indem es die
1265             <methodname>describeTable()</methodname> Methode des Adapters verwendet. Operationen
1266             die diese Einsicht benötigten sind:
1267         </para>
1269         <itemizedlist>
1270             <listitem><para><methodname>insert()</methodname></para></listitem>
1271             <listitem><para><methodname>find()</methodname></para></listitem>
1272             <listitem><para><methodname>info()</methodname></para></listitem>
1273         </itemizedlist>
1275         <para>
1276             In einigen Fällen, speziell wenn viele Table Objekte auf der gleichen Datenbanktabelle
1277             instanziert werden kann das Abfragen der Datenbank nach den Metadaten der Tabelle für
1278             jede Instanz unerwünscht sein wegen der Geschwindigkeit. In solchen Fällen, können
1279             Benutzer davon profitieren das die Metadaten der Tabelle, die von der Datenbank
1280             empfangen werden, gecached werden.
1281         </para>
1283         <para>
1284             Es gibt zwei grundsätzliche Wege bei denen ein Benutzer Vorteile davon haben kann wenn
1285             die Metadaten der Tabelle gecached werden:
1286         </para>
1288         <itemizedlist>
1289             <listitem>
1290                 <para>
1291                     <emphasis>Aufruf von
1292                         <methodname>Zend_Db_Table_Abstract::setDefaultMetadataCache()</methodname></emphasis>
1293                     - Das erlaubt es Entwicklern das Standardcacheobjekt zu setzen das für alle
1294                     Tabellenklassen verwendet werden soll.
1295                 </para>
1296             </listitem>
1298             <listitem>
1299                 <para>
1300                     <emphasis>Konfigurieren von
1301                     <methodname>Zend_Db_Table_Abstract::__construct()</methodname></emphasis> -
1302                     Das erlaubt es Entwicklern das Cacheobjekt zu setzen das für eine spezielle
1303                     Instanz der Tabellenklasse verwendet werden soll.
1304                 </para>
1305             </listitem>
1306         </itemizedlist>
1308         <para>
1309             In beiden Fällen muß die Spezifikation des Caches entweder <constant>NULL</constant>
1310             (wenn kein Cache verwendet wird) oder eine Instanz von
1311             <link linkend="zend.cache.frontends.core"><classname>Zend_Cache_Core</classname></link>
1312             sein. Die Methoden können in Verbindung zueinander verwendet werden wenn es gewünscht
1313             ist beides zu haben, einen standardmäßigen Cache für die Metadaten und die Möglichkeit
1314             den Cache eines individuellen Tabellenobjektes zu ändern.
1315         </para>
1317         <example id="zend.db.table.metadata.caching-default">
1318             <title>
1319                 Verwenden eines standardmäßigen Caches für Metadaten für alle Tabellenobjekte
1320             </title>
1322             <para>
1323                 Der folgende Code demonstriert wie ein standardmäßiger Cache für die Metadaten
1324                 gesetzt werden kann der für alle Tabellenobjekte verwendet wird:
1325             </para>
1327             <programlisting language="php"><![CDATA[
1328 // Zuerst muß der Cache vorbereitet werden
1329 $frontendOptions = array(
1330     'automatic_serialization' => true
1331     );
1333 $backendOptions  = array(
1334     'cache_dir'                => 'cacheDir'
1335     );
1337 $cache = Zend_Cache::factory('Core',
1338                              'File',
1339                              $frontendOptions,
1340                              $backendOptions);
1342 // Als nächstes, den Cache setzen der mit allen Tabellenobjekten verwendet werden soll
1343 Zend_Db_Table_Abstract::setDefaultMetadataCache($cache);
1345 // Eine Tabellenklasse wird auch benötigt
1346 class Bugs extends Zend_Db_Table_Abstract
1348     // ...
1351 // Jede Instanz von Bugs verwenden nur den Standardmäßigen Cache für die Metadaten
1352 $bugs = new Bugs();
1353 ]]></programlisting>
1354         </example>
1356         <example id="zend.db.table.metadata.caching-instance">
1357             <title>Einen Metadaten Cache für ein spezielles Tabellenobjekt verwenden</title>
1359             <para>
1360                 Der folgende Code demonstriert wie ein Cache für Metadaten für eine spezielle
1361                 Instanz eines Tabellenobjektes gesetzt werden kann:
1362             </para>
1364             <programlisting language="php"><![CDATA[
1365 // Zuerst den Cache vorbereiten
1366 $frontendOptions = array(
1367     'automatic_serialization' => true
1368     );
1370 $backendOptions  = array(
1371     'cache_dir'                => 'cacheDir'
1372     );
1374 $cache = Zend_Cache::factory('Core',
1375                              'File',
1376                              $frontendOptions,
1377                              $backendOptions);
1379 // Eine Tabellenklasse wird auch benötigt
1380 class Bugs extends Zend_Db_Table_Abstract
1382     // ...
1385 // Eine Instanz für die Instanzierung konfgurieren
1386 $bugs = new Bugs(array('metadataCache' => $cache));
1387 ]]></programlisting>
1388         </example>
1390         <note>
1391             <title>Automatische Serialisierung mit dem Cache Frontend</title>
1393             <para>
1394                 Da die Information die von der <methodname>describeTable()</methodname> Methode des
1395                 Adapters zurückgegeben wird, ein Array ist, muß sichergestellt werden das die
1396                 <property>automatic_serialization</property> Option für das
1397                 <classname>Zend_Cache_Core</classname> Frontend auf <constant>TRUE</constant>
1398                 gesetzt wird.
1399             </para>
1400         </note>
1402         <para>
1403             Obwohl die obigen Beispiele <classname>Zend_Cache_Backend_File</classname> verwenden,
1404             können Entwickler jegliches Cache Backend verwenden das der Situation am besten
1405             entspricht. Siehe <link linkend="zend.cache">Zend_Cache</link> für weitere
1406             Informationen.
1407         </para>
1409         <sect3 id="zend.db.table.metadata.caching.hardcoding">
1410             <title>Tabellen Metadaten hardcoden</title>
1412             <para>
1413                 Um das Cachen von Metadaten einen weiteren Schritt weiterzubringen, kann man sich
1414                 auch entscheiden die Metadaten hardzucoden. In diesem speziellen Fall benötigt jede
1415                 Änderung trotzdem eine Änderung im Code. Als solches, ist es nur empfohlen für jene
1416                 die eine Produktionsumgebung optimieren wollen.
1417             </para>
1419             <para>
1420                 Die Struktur der Metadaten ist wie folgt:
1421             </para>
1423             <programlisting language="php"><![CDATA[
1424 protected $_metadata = array(
1425     '<column_name>' => array(
1426         'SCHEMA_NAME'      => <string>,
1427         'TABLE_NAME'       => <string>,
1428         'COLUMN_NAME'      => <string>,
1429         'COLUMN_POSITION'  => <int>,
1430         'DATA_TYPE'        => <string>,
1431         'DEFAULT'          => NULL|<value>,
1432         'NULLABLE'         => <bool>,
1433         'LENGTH'           => <string - length>,
1434         'SCALE'            => NULL|<value>,
1435         'PRECISION'        => NULL|<value>,
1436         'UNSIGNED'         => NULL|<bool>,
1437         'PRIMARY'          => <bool>,
1438         'PRIMARY_POSITION' => <int>,
1439         'IDENTITY'         => <bool>,
1440     ),
1441     // additional columns...
1443 ]]></programlisting>
1445             <para>
1446                 Ein einfacher Weg um die richtigen Werte zu erhalten ist es den Metadaten Cache zu
1447                 verwenden, und dann die Werte die im Cache gespeichert sind, zu deserialisieren.
1448             </para>
1450             <para>
1451                 Diese Optimierung kann ausgeschaltet werden indem das
1452                 <property>metadataCacheInClass</property> Flag ausgeschaltet wird:
1453             </para>
1455             <programlisting language="php"><![CDATA[
1456 // Bei der Instanziierung:
1457 $bugs = new Bugs(array('metadataCacheInClass' => false));
1459 // Oder später:
1460 $bugs->setMetadataCacheInClass(false);
1461 ]]></programlisting>
1463             <para>
1464                 Das Flag ist standardmäßig aktiviert, was sicherstellt dass das
1465                 <varname>$_metadata</varname> Array nur einmal pro Instanz ausgeliefert wird.
1466             </para>
1467         </sect3>
1468     </sect2>
1470     <sect2 id="zend.db.table.extending">
1471         <title>Eine Table Klasse erweitern und anpassen</title>
1473         <sect3 id="zend.db.table.extending.row-rowset">
1474             <title>Verwenden eigener Zeilen oder Rowset Klassen</title>
1476             <para>
1477                 Standardmäßig geben die Methoden der Table Klasse ein Rowset als Instanzen der
1478                 konkreten Klasse <classname>Zend_Db_Table_Rowset</classname>, und Rowsets enthalten
1479                 eine Kollektion von Instanzen der konkreten Klasse
1480                 <classname>Zend_Db_Table_Row</classname>. Eine alternative Klasse kann für jede von
1481                 Ihnen als alternative Klasse definiert werden die verwendet werden soll, aber es
1482                 müssen Klassen sein die <classname>Zend_Db_Table_Rowset_Abstract</classname>
1483                 erweitern und respektiv <classname>Zend_Db_Table_Row_Abstract</classname>.
1484             </para>
1486             <para>
1487                 Es können Zeilen und Rowset Klassen definiert werden indem das Optionsarray des
1488                 Table Konstruktors verwendet wird, respektiv die Schlüssel
1489                 '<property>rowClass</property>' und '<property>rowsetClass</property>'. Die Namen
1490                 der Klassen müssen spezifiziert werden indem Strings verwendet werden.
1491             </para>
1493             <example id="zend.db.table.extending.row-rowset.example">
1494                 <title>
1495                     Beispiel dafür wie die Zeilen und Rowset Klassen spezifiziert werden können
1496                 </title>
1498                 <programlisting language="php"><![CDATA[
1499 class My_Row extends Zend_Db_Table_Row_Abstract
1501     ...
1504 class My_Rowset extends Zend_Db_Table_Rowset_Abstract
1506     ...
1509 $table = new Bugs(
1510     array(
1511         'rowClass'    => 'My_Row',
1512         'rowsetClass' => 'My_Rowset'
1513     )
1516 $where = $table->getAdapter()->quoteInto('bug_status = ?', 'NEW')
1518 // Gibt ein Objekt des Typs My_Rowset zurück
1519 // das ein Array von Objekten des Typs My_Row enthält.
1520 $rows = $table->fetchAll($where);
1521 ]]></programlisting>
1522             </example>
1524             <para>
1525                 Die Klassen können geändert werden indem Sie mit den
1526                 <methodname>setRowClass()</methodname> und
1527                 <methodname>setRowsetClass()</methodname> Methoden spezifiziert werden. Das
1528                 entspricht den Zeilen und Rowsets die nachfolgend erstellt werden; es ändert aber
1529                 nicht die Klasse von Zeilen- oder Rowsetobjekten die bereits davor erstellt wurden.
1530             </para>
1532             <example id="zend.db.table.extending.row-rowset.example2">
1533                 <title>Beispiel für das Ändern von Zeilen und Rowset Klassen</title>
1535                 <programlisting language="php"><![CDATA[
1536 $table = new Bugs();
1538 $where = $table->getAdapter()->quoteInto('bug_status = ?', 'NEW')
1540 // Gibt ein Objekt vom Typ Zend_Db_Table_Rowset zurück das ein Array
1541 // von Objekten des Typs Zend_Db_Table_Row enthält.
1542 $rowsStandard = $table->fetchAll($where);
1544 $table->setRowClass('My_Row');
1545 $table->setRowsetClass('My_Rowset');
1547 // Gibt ein Objekt vom Typ My_Rowset zurück das ein Array
1548 // von Objekten des Typs My_Row enthält.
1549 $rowsCustom = $table->fetchAll($where);
1551 // Das $rowsStandard Objekt existiert noch immer, und es bleibt unverändert.
1552 ]]></programlisting>
1553             </example>
1555             <para>
1556                 Für weitere Informationen über Zeilen und Rowset Klassenm siehe
1557                 <link linkend="zend.db.table.row">dieses Kapitel</link> und <link
1558                     linkend="zend.db.table.rowset">dieses hier</link>.
1559             </para>
1560         </sect3>
1562         <sect3 id="zend.db.table.extending.insert-update">
1563             <title>Selbst definierte Logik für das Einfügen, Aktualisieren und Löschen</title>
1565             <para>
1566                 Die <methodname>insert()</methodname> und <methodname>update()</methodname>
1567                 Methoden in der Table Klasse können überschrieben werden. Das bietet die
1568                 Möglichkeit eigenen Code einzufügen der ausgeführt wird bevor die Datenbank
1569                 Operation durchgeführt wird. Es muß sichergestellt werden das die Methode der
1570                 Elternklasse aufgerufen wird wenn man fertig ist.
1571             </para>
1573             <example id="zend.db.table.extending.insert-update.example">
1574                 <title>Eigene Logik um Zeitstempel zu managen</title>
1576                 <programlisting language="php"><![CDATA[
1577 class Bugs extends Zend_Db_Table_Abstract
1579     protected $_name = 'bugs';
1581     public function insert(array $data)
1582     {
1583         // Einen Zeitstempel hinzufügen
1584         if (empty($data['created_on'])) {
1585             $data['created_on'] = time();
1586         }
1587         return parent::insert($data);
1588     }
1590     public function update(array $data, $where)
1591     {
1592         // Einen Zeitstempel hinzufügen
1593         if (empty($data['updated_on'])) {
1594             $data['updated_on'] = time();
1595         }
1596         return parent::update($data, $where);
1597     }
1599 ]]></programlisting>
1600             </example>
1602             <para>
1603                 Auch die <methodname>delete()</methodname> Methode kann überschrieben werden.
1604             </para>
1605         </sect3>
1607         <sect3 id="zend.db.table.extending.finders">
1608             <title>Eigene Such Methoden in Zend_Db_Table definieren</title>
1610             <para>
1611                 Es können eigene Abfrage Methoden in der Table Klasse implementiert werden, wenn oft
1612                 die Notwendigkeit besteht Abragen mit speziellen Kriterien auf der Table Klasse
1613                 durchzuführen. Die meisten Abfragen können mit <methodname>fetchAll()</methodname>
1614                 geschrieben werden, das bedeutet aber das Code dupliziert werden muß um
1615                 Abfragekonditionen zu formen die Abfrage in verschiedenen Orten der Anwendung
1616                 auszuführen. Hierfür kann es nützlich sein eine Methode in der Table Klasse zu
1617                 definieren um oft benutzte Abfragen an dieser Tabelle durchzuführen.
1618             </para>
1620             <example id="zend.db.table.extending.finders.example">
1621                 <title>Eigene Methode um Fehler durch den Status zu finden</title>
1623                 <programlisting language="php"><![CDATA[
1624 class Bugs extends Zend_Db_Table_Abstract
1626     protected $_name = 'bugs';
1628     public function findByStatus($status)
1629     {
1630         $where = $this->getAdapter()->quoteInto('bug_status = ?', $status);
1631         return $this->fetchAll($where, 'bug_id');
1632     }
1634 ]]></programlisting>
1635             </example>
1636         </sect3>
1638         <sect3 id="zend.db.table.extending.inflection">
1639             <title>Inflection (Beugung) in Zend_Db_Table definieren</title>
1641             <para>
1642                 Einige Leute bevorzugen das der Name der Table Klasse einem Tabellennamen in der
1643                 <acronym>RDBMS</acronym>, durch eine Stringumwandlung die
1644                 <emphasis>Inflection</emphasis> (Beugung) genannt wird, entspricht.
1645             </para>
1647             <para>
1648                 Wenn zum Beispiel der Name der Table Klasse "BugsProducts" ist, würde
1649                 Sie der physikalischen Tabelle in der Datenbank entsprechen die
1650                 "bugs_products" heißt, wenn die explizite Definition der
1651                 <varname>$_name</varname> Eigenschaft der Klasse unterdrückt wird. In dieser
1652                 Übereinstimmung der Beugung, wird der Klassenname im "CamelCase" Format geschrieben
1653                 und in Kleinschreibung transformiert, und Wörter mit einem Unterstrich seperiert.
1654             </para>
1656             <para>
1657                 Der Tabellenname der Datenbank kann unabhängig vom Klassennamen spezifiziert werden
1658                 indem der Tabellenname mit der Klasseneigenschaft <varname>$_name</varname> in jeder
1659                 der eigenen Tabellenklassen deklariert wird.
1660             </para>
1662             <para>
1663                 <classname>Zend_Db_Table_Abstract</classname> führt keine Beugung durch um die
1664                 Klassennamen mit den Tabellennamen in Übereinstimmung zu bringen. Wenn die
1665                 Deklaration von <varname>$_name</varname> in der eigenen Tabellenklasse unterdrückt
1666                 wird, wird die Klasse mit der Datenbanktabelle in Verbindung gebracht die der
1667                 Schreibweise des Klassennamens exakt entspricht.
1668             </para>
1670             <para>
1671                 Es ist unzureichend Identifizierer von der Datenbank zu transformieren, da das zu
1672                 Doppeldeutigkeiten führen kann oder einige Identifizierer sogar unerreichbar macht.
1673                 Die Verwendung der <acronym>SQL</acronym> Identifizierer exakt so wie Sie in der
1674                 Datenbank vorhanden sind, macht <classname>Zend_Db_Table_Abstract</classname> sowohl
1675                 einfacher als auch flexibler.
1676             </para>
1678             <para>
1679                 Wenn man es vorzieht Beugung zu verwenden, muß die Transformation selbst durch das
1680                 Überschreiben der <methodname>_setupTableName()</methodname> Methode in der eigenen
1681                 Tabellenklasse implementiert werden. Ein Weg um das zu tun ist die Definition einer
1682                 abstrakten Klase die <classname>Zend_Db_Table_Abstract</classname> erweitert. Der
1683                 Rest der eigenen Klassen erweitert dann die eigene neue abstrakte Klasse.
1684             </para>
1686             <example id="zend.db.table.extending.inflection.example">
1687                 <title>Beispiel einer abstrakten Tabellenklasse die Beugung implementiert</title>
1689                 <programlisting language="php"><![CDATA[
1690 abstract class MyAbstractTable extends Zend_Db_Table_Abstract
1692     protected function _setupTableName()
1693     {
1694         if (!$this->_name) {
1695             $this->_name = myCustomInflector(get_class($this));
1696         }
1697         parent::_setupTableName();
1698     }
1701 class BugsProducts extends MyAbstractTable
1704 ]]></programlisting>
1705             </example>
1707             <para>
1708                 Man ist selbst für das Schreiben von Funktionen verantwortlich um die Transformation
1709                 der Beugung auszuführen. Zend Framework bietet solche Funktionen nicht an.
1710             </para>
1711         </sect3>
1712     </sect2>
1713 </sect1>