| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- EN-Revision: 24249 -->
- <!-- 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.concrete">
- <title>Zend_Db_Table als konkrete Klasse verwenden</title>
- <para>
- Ab Zend Framework 1.9 kann man <classname>Zend_Db_Table</classname> instanziieren. Der
- zusätzliche Vorteil ist das man die Basisklasse nicht erweitern und konfigurieren muß um
- einfache Operationen wie auswählen, einfügen, aktualisieren und löschen in einer
- einzelnen Tabelle durchzuführen. Anbei ist ein Beispiel der einfachsten Verwendung.
- </para>
- <example id="zend.db.table.defining.concrete-instantiation.example1">
- <title>Eine Table Klasse nur mit dem Stringnamen deklarieren</title>
- <programlisting language="php"><![CDATA[
- Zend_Db_Table::setDefaultAdapter($dbAdapter);
- $bugTable = new Zend_Db_Table('bug');
- ]]></programlisting>
- </example>
- <para>
- Das obige Beispiel zeigt das einfachste Beispiel. Nicht alle der unten beschriebenen
- Optionen sollten für die Konfiguration von <classname>Zend_Db_Table</classname> Tabellen
- durchgeführt werden. Wenn man in der Lage sein will das konkrete Verwendungsbeispiel
- zusätzlich zu den komplexeren Abhängigkeits Features zu verwenden sehen Sie in die
- <classname>Zend_Db_Table_Definition</classname> Dokumentation.
- </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 <varname>$_name</varname> 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 language="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 language="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 <varname>$_schema</varname> oder mit dem Schema vorangestellt in der
- <varname>$_name</varname> Eigenschaft. Jedes Schema welches in der
- <varname>$_name</varname> Eigenschaft angegeben ist wird vorrangig gegenüber dem
- Schema der <varname>$_schema</varname> Eigenschaft behandelt. In einigen
- <acronym>RDBMS</acronym> 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 language="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
- <varname>$_name</varname> und <varname>$_schema</varname> Eigenschaften,
- überschreiben. Eine Schema Angabe welche mit der <property>name</property> Directive
- angegeben wurde überschreibt jeglichen Wert welcher von der
- <property>schema</property> 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 language="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 <varname>$_primary</varname> 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 language="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
- <methodname>describeTable()</methodname> 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
- <methodname>describeTable()</methodname> 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 language="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>
- <methodname>_setupDatabaseAdapter()</methodname> ü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>
- <methodname>_setupTableName()</methodname> 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>
- <methodname>_setupMetadata()</methodname> setzt das Schema wenn der
- Tabellenname dem Muster "<command>schema.table</command>" entspricht; ruft
- <methodname>describeTable()</methodname> auf um Metadaten Informationen zu
- erhalten; Standardisiert das <varname>$_cols</varname> Array auf die
- Spalten wie von <methodname>describeTable()</methodname> geliefert. Durch
- das Überschreiben dieser Methode können die Spalten angegeben werden.
- </para>
- </listitem>
- <listitem>
- <para>
- <methodname>_setupPrimaryKey()</methodname> standardisiert die
- Primärschlüssel Spalten zu denen geliefert von
- <methodname>describeTable()</methodname>; prüft ob die Primärschlüssel
- Spalten im <varname>$_cols</varname> 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
- <methodname>init()</methodname> Methode zu verschieben, die aufgerufen wird nachdem
- alle Tabellen Metadaten bearbeitet wurden. Das ist besser als die
- <methodname>__construct()</methodname> Methode wenn die Metadaten nicht
- programmtechnisch verändert werden sollen.
- </para>
- <example id="zend.db.table.defining.init.usage.example">
- <title>Beispielverwendung der init() Methode</title>
- <programlisting language="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_observer;
- public function init()
- {
- $this->_observer = new MyObserverClass();
- }
- }
- ]]></programlisting>
- </example>
- </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 <acronym>RDBMS</acronym> 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 '<property>db</property>', 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 language="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
- <methodname>Zend_Db_Table_Abstract::setDefaultAdapter()</methodname> 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 language="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
- '<property>db</property>' 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 language="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 <acronym>RDBMS</acronym>
- 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 <methodname>insert()</methodname> 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 language="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 <acronym>SQL</acronym>
- 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 language="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 <acronym>SQL</acronym>
- <constant>INSERT</constant> Anweisung unterdrückt wird.
- </para>
- <para>
- Wenn die geschützte Variable <varname>$_sequence</varname>, in
- <classname>Zend_Db_Table_Abstract</classname>, als boolscher Wert
- <constant>TRUE</constant> 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 language="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 <acronym>SQL</acronym> Server, und SQLite sind Beispiele von
- <acronym>RDBMS</acronym> Marken die automatische Primärschlüssel unterstützen.
- </para>
- <para>
- PostgreSQL hat eine <constant>SERIAL</constant> 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.
- <acronym>IBM</acronym> <acronym>DB2</acronym> hat eine
- <constant>IDENTITY</constant> 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
- <varname>$_sequence</varname> auf <constant>TRUE</constant> 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 <varname>$_sequence</varname> 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 <constant>INSERT</constant>
- 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 language="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs';
- protected $_sequence = 'bug_sequence';
- }
- ]]></programlisting>
- </example>
- <para>
- Oracle, PostgreSQL, und <acronym>IBM</acronym> <acronym>DB2</acronym> sind Beispiele
- von <acronym>RDBMS</acronym> Marken die Sequenz Objekte in der Datenbank
- unterstützen.
- </para>
- <para>
- PostgreSQL und <acronym>IBM</acronym> <acronym>DB2</acronym> 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 <varname>$_sequence</varname> als boolsches <constant>FALSE</constant>
- 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
- <methodname>insert()</methodname> 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 language="php"><![CDATA[
- class BugStatus extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bug_status';
- protected $_sequence = false;
- }
- ]]></programlisting>
- </example>
- <note>
- <para>
- Alle <acronym>RDBMS</acronym> 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
- <methodname>update()</methodname> 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 <acronym>SQL</acronym>
- Ausdruck der in der <constant>WHERE</constant> Klausel verwendet wird, als Kriterium für
- die Zeilen die in der <constant>UPDATE</constant> 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 language="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 <methodname>update()</methodname> Methode der Tabelle zur
- <link linkend="zend.db.adapter.write.update"><methodname>update()</methodname></link>
- Methode des Datenbank Adapters weiterleitet, kann das zweite Argument ein Array von
- <acronym>SQL</acronym> Ausdrücken sein. Diese Ausdrücke werden als Boolsche Terme
- kombiniert indem ein <constant>AND</constant> Operator verwendet wird.
- </para>
- <note>
- <para>
- Die Werte und Identifizierer im <acronym>SQL</acronym> 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 dies getan
- wird. Die <methodname>quote()</methodname>, <methodname>quoteInto()</methodname> und
- <methodname>quoteIdentifier()</methodname> 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
- <methodname>delete()</methodname> Methode verwendet wird. Diese Methode nimmt ein
- Argument, welches ein <acronym>SQL</acronym> Ausdruck ist, der in der
- <constant>WHERE</constant> 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 language="php"><![CDATA[
- $table = new Bugs();
- $where = $table->getAdapter()->quoteInto('bug_id = ?', 1235);
- $table->delete($where);
- ]]></programlisting>
- </example>
- <para>
- Da die <methodname>delete()</methodname> Methode der Tabelle zur
- <link linkend="zend.db.adapter.write.delete"><methodname>delete()</methodname></link>
- Methode des Datenbank Adapters weiterleitet, kann das Argument ein Array von
- <acronym>SQL</acronym> Ausdrücken sein. Diese Ausdrücke werden als boolsche Terme
- kombiniert indem ein <constant>AND</constant> Operator verwendet wird.
- </para>
- <note>
- <para>
- Die Werte und Identifizierer im <acronym>SQL</acronym> 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 dies getan
- wird. Die <methodname>quote()</methodname>, <methodname>quoteInto()</methodname> und
- <methodname>quoteIdentifier()</methodname> 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 <methodname>find()</methodname> 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 language="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 <methodname>find()</methodname> 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
- <methodname>find()</methodname> 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
- <methodname>find()</methodname> 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 <methodname>find()</methodname> 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 language="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>
- <warning>
- <para>
- Die <acronym>API</acronym> 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
- <methodname>fetchRow()</methodname> und <methodname>fetchAll()</methodname>
- 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>
- <programlisting language="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)
- );
- // oder mit Bindung
- $rows = $table->fetchAll(
- $table->select()
- ->where('bug_status = :status')
- ->bind(array(':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')
- );
- // oder mit Bindung
- $row = $table->fetchRow(
- $table->select()
- ->where('bug_status = :status')
- ->bind(array(':status'=>'NEW')
- ->order('bug_id ASC')
- );
- ]]></programlisting>
- </warning>
- <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 <methodname>save()</methodname> Operationen
- verwendet werden kann. Eine <classname>Zend_Db_Table_Row</classname> mit
- <property>readOnly</property> Status wird eine Exception werfen wenn eine
- <methodname>save()</methodname> Operation versucht wird.
- </para>
- </listitem>
- <listitem>
- <para>
- Man <emphasis>kann</emphasis> <constant>JOIN</constant> 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 oder Zeilenset zurückgegeben werden.
- Wenn das versucht wird, wird ein <acronym>PHP</acronym> Fehler getriggert.
- Das wurde getan um Sicherzustellen das die Integrität von
- <classname>Zend_Db_Table</classname> gewahrt bleibt. z.B. ein
- <classname>Zend_Db_Table_Row</classname> sollte nur Spalten referenzieren
- die von seiner Elterntabelle abgeleitet sind.
- </para>
- </listitem>
- </itemizedlist>
- <example id="zend.db.table.qry.rows.set.simple.usage.example">
- <title>Einfache Verwendung</title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- $select = $table->select();
- $select->where('bug_status = ?', 'NEW');
- $rows = $table->fetchAll($select);
- ]]></programlisting>
- </example>
- <para>
- Flüssige Interfaces sind über alle Komponenten hinweg implementiert, sodass dies zu
- einer abgekürzteren Form umgeschrieben werden kann.
- </para>
- <example id="zend.db.table.qry.rows.set.fluent.interface.example">
- <title>Beispiel des Fluent Interfaces</title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- $rows =
- $table->fetchAll($table->select()->where('bug_status = ?', 'NEW'));
- ]]></programlisting>
- </example>
- </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
- <methodname>fetchAll()</methodname> 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 language="php"><![CDATA[
- $table = new Bugs();
- $select = $table->select()->where('bug_status = ?', 'NEW');
- $rows = $table->fetchAll($select);
- ]]></programlisting>
- </example>
- <para>
- Der <constant>ORDER</constant> BY 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
- <constant>LIMIT</constant> Klausel verwendet oder in einer ähnlichen Logik für
- <acronym>RDBMS</acronym> Marken welche die <constant>LIMIT</constant> 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 language="php"><![CDATA[
- $table = new Bugs();
- $order = 'bug_id';
- // Gibt die Zeilen 21 bis 30 zurück
- $count = 10;
- $offset = 20;
- $select = $table->select()->where('bug_status = ?' => 'NEW')
- ->order($order)
- ->limit($count, $offset);
- $rows = $table->fetchAll($select);
- ]]></programlisting>
- </example>
- <para>
- Alle diese Argumente sind optional. Wenn die <constant>ORDER</constant> Klausel
- unterdrückt wird, dann enthält das Ergebnis die Zeilen der Tabelle in einer
- unvorhersagbaren Reihenfolge. Wenn keine <constant>LIMIT</constant> Klausel gesetzt
- ist, dann wird jede Zeile dieser Tabelle zurückgegeben die der
- <constant>WHERE</constant> 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 oder Sets zu limitieren. Das kann durch die Übergabe einer
- <constant>FROM</constant> Klausel an das Select Objekt getan werden. Das erste
- Argument in der <constant>FROM</constant> 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>
- <example id="zend.db.table.qry.rows.set.retrieving.a.example">
- <title>Spezielle Spalten erhalten</title>
- <programlisting language="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>
- <important>
- <para>
- Das Rowset enthält Zeilen die trotzdem 'gültig' sind - sie enthalten bloß
- ein Subset der Spalten einer Tabelle. Wenn eine <methodname>save()</methodname>
- Methode auf dem Teil einer Zeile aufgerufen wird dann werden nur die vorhandenen
- Felder geändert.
- </para>
- </important>
- <para>
- Es können Ausdrücke in einer <constant>FROM</constant> Klausel spezifiziert werden
- die dann als readOnly Zeile oder 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 <constant>GROUP</constant> 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>
- <example id="zend.db.table.qry.rows.set.retrieving.b.example">
- <title>Ausdrücke als Spalten erhalten</title>
- <programlisting language="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>
- <para>
- 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>
- <example id="zend.db.table.qry.rows.set.refine.example">
- <title>Beispiel für das Finden von Zeilen durch einen Ausdruck</title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- // Bei gesetztem From Abschnitt empfangen, wichtig wenn gejoint werden soll
- $select = $table->select(Zend_Db_Table::SELECT_WITH_FROM_PART);
- $select->setIntegrityCheck(false)
- ->where('bug_status = ?', 'NEW')
- ->join('accounts', 'accounts.account_name = bugs.reported_by')
- ->where('accounts.account_name = ?', 'Bob');
- $rows = $table->fetchAll($select);
- ]]></programlisting>
- </example>
- <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 <constant>SELECT</constant> 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 <constant>FALSE</constant> Wertes an
- <methodname>setIntegrityCheck()</methodname> zu erhalten. Das resultierende Zeilen
- oder Zeilenset wird als eine 'locked' Zeile zurückgegeben (das bedeutet das
- <methodname>save()</methodname>, <methodname>delete()</methodname> und jede andere
- Methode 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 language="php"><![CDATA[
- $table = new Bugs();
- $select = $table->select(Zend_Db_Table::SELECT_WITH_FROM_PART)
- ->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 <methodname>fetchAll()</methodname> 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 language="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 <methodname>fetchRow()</methodname> <acronym>PHP</acronym>'s
- <constant>NULL</constant> 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 <methodname>info()</methodname> 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 language="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 <methodname>info()</methodname> Methode
- zurückgegeben wird sind anbei beschrieben:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>name</emphasis> => der Name der Tabelle.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>cols</emphasis> => ein Array das die Spalte(n) der Tabelle benennt.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>primary</emphasis> => ein Array das die Spalte(n) des Primärschlüssels
- benennt.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>metadata</emphasis> => ein assoziatives Array das die Spaltennamen
- mit Informationen über die Spalten zusammenführt. Das ist die Information die
- durch die <methodname>describeTable()</methodname> Methode zurückgegeben wird.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>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>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>referenceMap</emphasis> => ist ein assoziatives Array von
- Klassennamen von Tabellen die diese Tabelle referenzieren. Siehe
- <link linkend="zend.db.table.relationships.defining">dieses Kapitel</link>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>dependentTables</emphasis> => ein Array von Klassennamen von
- Tabellen die diese Tabelle referenzieren. Siehe
- <link linkend="zend.db.table.relationships.defining">dieses Kapitel</link>.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>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
- <methodname>describeTable()</methodname> Methode des Adapters verwendet. Operationen
- die diese Einsicht benötigten sind:
- </para>
- <itemizedlist>
- <listitem><para><methodname>insert()</methodname></para></listitem>
- <listitem><para><methodname>find()</methodname></para></listitem>
- <listitem><para><methodname>info()</methodname></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:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>Aufruf von
- <methodname>Zend_Db_Table_Abstract::setDefaultMetadataCache()</methodname></emphasis>
- - Das erlaubt es Entwicklern das Standardcacheobjekt zu setzen das für alle
- Tabellenklassen verwendet werden soll.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>Konfigurieren von
- <methodname>Zend_Db_Table_Abstract::__construct()</methodname></emphasis> -
- Das erlaubt es Entwicklern das Cacheobjekt zu setzen das für eine spezielle
- Instanz der Tabellenklasse verwendet werden soll.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- In beiden Fällen muß die Spezifikation des Caches entweder <constant>NULL</constant>
- (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 language="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 für 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 language="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 <methodname>describeTable()</methodname> Methode des
- Adapters zurückgegeben wird, ein Array ist, muß sichergestellt werden das die
- <property>automatic_serialization</property> Option für das
- <classname>Zend_Cache_Core</classname> Frontend auf <constant>TRUE</constant>
- 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 language="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
- <property>metadataCacheInClass</property> Flag ausgeschaltet wird:
- </para>
- <programlisting language="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 dass das
- <varname>$_metadata</varname> 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
- '<property>rowClass</property>' und '<property>rowsetClass</property>'. 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 language="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
- <methodname>setRowClass()</methodname> und
- <methodname>setRowsetClass()</methodname> 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 language="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
- <link linkend="zend.db.table.row">dieses Kapitel</link> und <link
- linkend="zend.db.table.rowset">dieses hier</link>.
- </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 <methodname>insert()</methodname> und <methodname>update()</methodname>
- 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 language="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 <methodname>delete()</methodname> 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 <methodname>fetchAll()</methodname>
- 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 language="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
- <acronym>RDBMS</acronym>, durch eine Stringumwandlung die
- <emphasis>Inflection</emphasis> (Beugung) genannt wird, entspricht.
- </para>
- <para>
- Wenn zum Beispiel der Name der Table Klasse "BugsProducts" ist, würde
- Sie der physikalischen Tabelle in der Datenbank entsprechen die
- "bugs_products" heißt, wenn die explizite Definition der
- <varname>$_name</varname> 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 <varname>$_name</varname> 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 <varname>$_name</varname> 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 <acronym>SQL</acronym> 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 <methodname>_setupTableName()</methodname> 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 language="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>
|