| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- EN-Revision: 17054 -->
- <!-- 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 ZF 1.9 kann man Zend_Db_Table 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 Zend_Db_Table 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
- Zend_Db_Table_Definition 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 RDBMS Marken ist die
- Bezeichnung für Schema "database" oder "tablespace", wird aber ähnlich verwendet.
- </para>
- <example id="zend.db.table.defining.table-schema.example3">
- <title>Angeben einer Table Klasse mit Schema</title>
- <programlisting 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 <code>name</code> Directive angegeben wurde
- überschreibt jeglichen Wert welcher von der <code>schema</code> Option
- bereitgestellt ist.
- </para>
- <example id="zend.db.table.defining.table-schema.example.constructor">
- <title>Angebend von Tabellen und Schemanamen während der Instanziierung</title>
- <programlisting 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
- <code>describeTable()</code> Methode zu ermitteln.
- </para>
- <note>
- <para>
- Jede Table Klasse muss wissen mit welche(r/n) Spalte(n) Zeilen eindeutig
- identifiziert werden können. Wenn keine Primärschlüssel Spalte(n) in der
- Klassendefinition oder als Argument für den Konstruktor angegeben wurde und
- nicht aus den Metadaten der Tabelle mit Hilfe der <code>describeTable()</code>
- Methode ermittelt werden kann, dann kann die Tabelle nicht mit
- <classname>Zend_Db_Table</classname> verwendet werden.
- </para>
- </note>
- </sect3>
- <sect3 id="zend.db.table.defining.setup">
- <title>Überschreiben von Table Setup Methoden</title>
- <para>
- Wenn eine Instanz einer Table Klasse erzeugt wird, ruft der Konstruktor einige
- protected Methoden auf, die Metadaten der Tabelle initialisieren. Jede dieser
- Methoden kann erweitert werden um Metadaten explizit anzugeben. Dabei darf nicht
- vergessen werden am Ende der eigenen Methode die gleichnamige Methode der
- Parentklasse aufzurufen.
- </para>
- <example id="zend.db.table.defining.setup.example">
- <title>Beispiel für das Überschreiben der _setupTableName() Methode</title>
- <programlisting 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>
- <code>_setupDatabaseAdapter()</code> überprüft ob ein Adapter bereitgestellt
- wird; nimmt einen Standardadapter aus der Registry, wenn benötigt. Durch das
- Überschreiben dieser Methode kann ein Datenbankadapter aus einer anderen
- Quelle gesetzt werden.
- </para>
- </listitem>
- <listitem>
- <para>
- <code>_setupTableName()</code> setzt den standard Tabellennamen auf den
- Namen der Klasse. Durch das Überschreiben dieser Methode kann der
- Tabellenname gesetzt werden bevor dieses Standardverhalten abläuft.
- </para>
- </listitem>
- <listitem>
- <para>
- <code>_setupMetadata()</code> setzt das Schema wenn der Tabellenname dem
- Muster "schema.table" entspricht; ruft <code>describeTable()</code> auf um
- Metadaten Informationen zu erhalten; Standardisiert das <varname>$_cols</varname>
- Array auf die Spalten wie von <code>describeTable()</code> geliefert. Durch
- das Überschreiben dieser Methode können die Spalten angegeben werden.
- </para>
- </listitem>
- <listitem>
- <para>
- <code>_setupPrimaryKey()</code> standardisiert die Primärschlüssel Spalten
- zu denen geliefert von <code>describeTable()</code>; prüft ob die
- Primärschlüssel Spalten im <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 <code>init()</code> Methode
- zu verschieben, die aufgerufen wird nachdem alle Tabellen Metadaten bearbeitet
- wurden. Das ist besser als die <code>__construct</code> Methode wenn die Metadaten
- nicht programmtechnisch verändert werden sollen.
- </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 RDBMS repräsentiert. Es gibt drei Möglichkeiten den Datenbankadapter
- einer Tabellenklasse anzugeben und diese sind unten beschrieben:
- </para>
- <sect3 id="zend.db.table.constructing.adapter">
- <title>Angeben eines Datenbankadapters</title>
- <para>
- Der erste Weg einen Datenbankadapter an eine Table Klasse bereitzustellen ist, ein
- Objekt des Typs <classname>Zend_Db_Adapter_Abstract</classname> im Options Array,
- bezeichnet mit dem Schlüssel <code>'db'</code>, zu übergeben.
- </para>
- <example id="zend.db.table.constructing.adapter.example">
- <title>
- Beispiel für das Erzeugen einer Tabelle mit Nutzung eines Adapterobjekts
- </title>
- <programlisting 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
- <classname>Zend_Db_Table_Abstract::setDefaultAdapter()</classname> getan werden. Das
- Argument ist ein Objekt des Typs <classname>Zend_Db_Adapter_Abstract</classname>.
- </para>
- <example id="zend.db.table.constructing.default-adapter.example">
- <title>Beispiel für das erstellen von Table mit einem Standardadapter</title>
- <programlisting 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 <code>'db'</code>
- Schlüssel identifiziert. Der String wird als Schlüssel der statischen
- <classname>Zend_Registry</classname> Instanz verwendet, wo der Eintrag mit dem
- Schlüssel ein Objekt des Typs <classname>Zend_Db_Adapter_Abstract</classname> ist.
- </para>
- <example id="zend.db.table.constructing.registry.example">
- <title>Beispiel für das Erzeugen von Table mit einem Registry Schlüssel</title>
- <programlisting 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 RDBMS Marke und
- Datenbankinstanz. Wenn die Anwendung Zugriff auf mehrere Datenbanken benötigt oder
- auch mehrere Datenbank Marken, dann müssen mehrere Adapter verwendet werden.
- </para>
- </sect3>
- </sect2>
- <sect2 id="zend.db.table.insert">
- <title>Zeilen in eine Tabelle einfügen</title>
- <para>
- Table Objekte können verwendet werden um Zeilen in die Datenbank Tabelle einzufügen auf
- der das Table Objekt basiert. Hierzu kann die <code>insert()</code> Methode des Table
- Objektes verwendet werden. Das Argument ist ein assoziatives Array, das Spalten Namen
- mit Werten verbindet.
- </para>
- <example id="zend.db.table.insert.example">
- <title>Beispiel für das Einfügen in eine Tabelle</title>
- <programlisting 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 SQL Ausdruck behandelt
- werden, muß sichergestellt werden das Sie sich von reinen Strings unterscheiden. Es kann
- ein Objekt vom Typ <classname>Zend_Db_Expr</classname> verwendet werden um das zu
- bewerkstelligen.
- </para>
- <example id="zend.db.table.insert.example-expr">
- <title>Beispiel für das Einfügen von Ausdrücken in einer Tabelle</title>
- <programlisting 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 SQL <code>INSERT</code> 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 SQL Server, und SQLite sind Beispiele von RDBMS Marken die
- automatische Primärschlüssel unterstützen.
- </para>
- <para>
- PostgreSQL hat eine <code>SERIAL</code> Notation die implizit eine Sequenz definiert
- die auf den Tabellen- und Spaltennamen basiert, und diese Sequenz verwendet, um
- einen Schlüsselwert für neue Zeilen zu erstellen. IBM DB2 hat eine
- <code>IDENTITY</code> Notation die ähnlich arbeitet. Wenn eine dieser Notationen
- verwendet wird, muß der <classname>Zend_Db_Table</classname> Klasse mitgeteilt
- werden das Sie eine automatische Spalte hat, indem <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 <code>INSERT</code> Operation
- verwendet.
- </para>
- <example id="zend.db.table.insert.key-sequence.example">
- <title>Beispiel für das Deklaration einer Tabelle mit einer Sequenz</title>
- <programlisting language="php"><![CDATA[
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs';
- protected $_sequence = 'bug_sequence';
- }
- ]]></programlisting>
- </example>
- <para>
- Oracle, PostgreSQL, und IBM DB2 sind Beispiele von RDBMS Marken die Sequenz Objekte
- in der Datenbank unterstützen.
- </para>
- <para>
- PostgreSQL und IBM DB2 haben auch einen Syntax der Sequenzen implizit definiert und
- diese mit Spalten assoziiert. Wenn diese Notation verwendet wird, muß der Tabelle
- gesagt werden das Sie eine automatische Schlüsselspalte besitzt. Der Name der
- Sequenz muß nur in den Fällen als String definiert werden in denen die Sequenz
- explizit aufgerufen wird um den nächsten Schlüsselwert zu erhalten.
- </para>
- </sect3>
- <sect3 id="zend.db.table.insert.key-natural">
- <title>Eine Tabelle mit einem natürlichen Schlüssel verwenden</title>
- <para>
- Einige Tabellen haben natürliche Schlüssel. Das bedeutet das der Schlüssel nicht
- automatisch durch die Tabelle oder eine Sequenz erstellt wird. Der Wert für den
- Primärschlüssel muß in diesem Fall selbst definiert werden.
- </para>
- <para>
- Wenn <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 <code>insert()</code> Methode übergeben
- werden, andernfalls wird diese Methode eine
- <classname>Zend_Db_Table_Exception</classname> werfen.
- </para>
- <example id="zend.db.table.insert.key-natural.example">
- <title>
- Beispiel für das Definieren einer Tabelle mit einem natürlichen Schlüssel
- </title>
- <programlisting language="php"><![CDATA[
- class BugStatus extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bug_status';
- protected $_sequence = false;
- }
- ]]></programlisting>
- </example>
- <note>
- <para>
- Alle RDBMS Marken unterstützen Tabellen mit natürlichen Schlüsseln. Beispiele
- von Tabellen die oft so definiert werden das Sie natürliche Schlüssel besitzen
- sind Lookup Tabellen, Durchschnitts Tabellen in viele-zu-viele Beziehungen, oder
- die meisten Tabellen mit komponierten Primärschlüsseln.
- </para>
- </note>
- </sect3>
- </sect2>
- <sect2 id="zend.db.table.update">
- <title>Zeilen in einer Tabelle aktualisieren</title>
- <para>
- Spalten können in der Datenbanktabelle aktualisiert werden indem die <code>update</code>
- Methode der Table Klasse verwendet wird. Diese Methode nimmt zwei Argumente: ein
- assoziatives Array von Spalten die geändert werden sollen und neue Werte die diesen
- Spalten hinzugefügt werden; und einen SQL Ausdruck der in der <code>WHERE</code> Klausel
- verwendet wird, als Kriterium für die Zeilen die in der <code>UPDATE</code> Operation
- geändert werden sollen.
- </para>
- <example id="zend.db.table.update.example">
- <title>Beispiel für das Aktualisieren von Zeilen in einer Tabelle</title>
- <programlisting 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 <code>update()</code> Methode der Tabelle zur
- <link linkend="zend.db.adapter.write.update"><code>update()</code></link> Methode des
- Datenbank Adapters weiterleitet, kann das zweite Argument ein Array von SQL Ausdrücken
- sein. Diese Ausdrücke werden als Boolsche Terme kombiniert indem ein <code>AND</code>
- Operator verwendet wird.
- </para>
- <note>
- <para>
- Die Werte und Identifizierer im SQL Ausdruck werden nicht in Anführungszeichen
- gesetzt. Wenn Werte oder Identifizierer vorhanden sind die das Setzen in
- Anführungszeichen benötigen, ist man selbst dafür zuständig das das getan wird. Die
- <code>quote()</code>, <code>quoteInto()</code> und <code>quoteIdentifier()</code>
- Methoden des Datenbank Adapters können dafür verwendet werden.
- </para>
- </note>
- </sect2>
- <sect2 id="zend.db.table.delete">
- <title>Zeilen aus einer Tabelle löschen</title>
- <para>
- Zeilen können von einer Datenbanktabelle gelöscht werden indem die <code>delete()</code>
- Methode verwendet wird. Diese Methode nimmt ein Argument, welches ein SQL Ausdruck ist,
- der in der <code>WHERE</code> Klausel als Kriterium dafür verwendet wird, welche Zeilen
- gelöscht werden sollen.
- </para>
- <example id="zend.db.table.delete.example">
- <title>Beispiel für das Löschen von Zeilen einer Tabelle</title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- $where = $table->getAdapter()->quoteInto('bug_id = ?', 1235);
- $table->delete($where);
- ]]></programlisting>
- </example>
- <para>
- Da die <code>delete()</code> Methode der Tabelle zur
- <link linkend="zend.db.adapter.write.delete"><code>delete()</code></link> Methode des
- Datenbank Adapters weiterleitet, kann das Argument ein Array von SQL Ausdrücken sein.
- Diese Ausdrücke werden als boolsche Terme kombiniert indem ein <code>AND</code> Operator
- verwendet wird.
- </para>
- <note>
- <para>
- Die Werte und Identifizierer im SQL Ausdruck werden nicht in Anführungszeichen
- gesetzt. Wenn Werte oder Identifizierer vorhanden sind die das Setzen in
- Anführungszeichen benötigen, ist man selbst dafür zuständig das das getan wird. Die
- <code>quote()</code>, <code>quoteInto()</code> und <code>quoteIdentifier()</code>
- Methoden des Datenbank Adapters können dafür verwendet werden.
- </para>
- </note>
- </sect2>
- <sect2 id="zend.db.table.find">
- <title>Zeilen durch den Primärschlüssel finden</title>
- <para>
- Die Datenbanktabelle kann nach passenden Zeilen für spezifizierte Werte im
- Primärschlüssel abgefragt werden, indem die <code>find()</code> Methode verwendet wird.
- Das erste Argument dieser Methode ist entweder ein einzelner Wert oder ein Array von
- Werten die dem Primärschlüssel dieser Tabelle entsprechen.
- </para>
- <example id="zend.db.table.find.example">
- <title>Beispiel für das Finden von Zeilen durch Werte des Primärschlüssels</title>
- <programlisting 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 <code>find()</code> Methode kann weniger Zeilen zurückgeben als die Anzahl an Werten
- die für den Primärschlüssel definiert wurden, wenn einige der Werte keiner Zeile in der
- Datenbank Tabelle entsprechen. Die Methode kann sogar null Zeilen zurückgeben. Weil die
- Anzahl an zurückgegebenen Zeilen variabel ist, gibt die <code>find()</code> Methode ein
- Objekt vom Typ <classname>Zend_Db_Table_Rowset_Abstract</classname> zurück.
- </para>
- <para>
- Wenn der Primärschlüssel ein komponierter Schlüssel ist, als einer der aus mehreren
- Spalten besteht, können die zusätzlichen Spalten als zusätzliche Argumente in der
- <code>find()</code> Methode definiert werden. Es müssen soviele Argumente angegeben
- werden wie Spalten im Primärschlüssel der Tabelle existieren.
- </para>
- <para>
- Um mehrere Zeilen von einer Tabelle mit einem kombinierten Primärschlüssel zu finden,
- muß ein Array für jedes der Argumente übergeben werden. Alle dieser Arrays müssen die
- gleiche Anzahl an Elementen haben. Die Werte in jedem Array werden in Tupeln geformt und
- gereiht; zum Beispiel definiert das erste Element in allen Array Argumenten den ersten
- kombinierten Wert des Primärschlüssels, das zweite Element von allen Arrays definiert
- den zweiten kombinierten Wert des Primärschlüssels, und so weiter.
- </para>
- <example id="zend.db.table.find.example-compound">
- <title>
- Beispiel für das Finden von Zeilen durch Werte von kombinierten Primärschlüsseln
- </title>
- <para>
- Der Aufruf von <code>find()</code> anbei um mehreren Zeilen zu entsprechen kann zwei
- Zeilen in der Datenbank entsprechen. Die erste Zeile muß den Wert des
- Primärenschlüssels (1234, 'ABC') haben, und die zweite Zeile den Wert des
- Primärschlüssels (5678, 'DEF').
- </para>
- <programlisting 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>
- <para>
- <warning>
- <para>
- Die API für die Hol-Operationen wurde ausgeweitet um einem
- <classname>Zend_Db_Table_Select</classname> Objekt zu erlauben die Abfrage
- zu modifizieren. Trotzdem wird die veraltete Verwendung der
- <code>fetchRow()</code> und <code>fetchAll()</code> Methoden weiterhin ohne
- Änderungen funktionieren.
- </para>
- <para>
- Die folgenden Ausdrücke sind gültig und funktionell identisch, trotzdem wird
- empfohlen den Code zu aktualisieren um Vorteil aus der neuen Verwendung zu
- ziehen wo das möglich ist.
- </para>
- <para>
- <programlisting 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)
- );
- // Eine einzelne Zeile holen
- $row = $table->fetchRow(
- 'bug_status = "NEW"',
- 'bug_id ASC'
- );
- $row = $table->fetchRow(
- $table->select()
- ->where('bug_status = ?', 'NEW')
- ->order('bug_id ASC')
- );
- ]]></programlisting>
- </para>
- </warning>
- </para>
- <para>
- Das <classname>Zend_Db_Table_Select</classname> Objekt ist eine Erweiterung des
- <classname>Zend_Db_Select</classname> Objekts das spezielle Einschränkungen zu einer
- Abfrage hinzufügt. Die Verbesserungen und Einschränkungen sind folgende:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- Man <emphasis>kann</emphasis> sich entscheiden ein Subset von Zeilen einer
- fetchRow oder fetchAll Abfrage zurückzuerhalten. Dann kann Vorteile durch
- Optimierung bieten, wenn die Rückgabe eines großes Sets an Ergebnissen für
- alle Zeilen nicht gewünscht wird.
- </para>
- </listitem>
- <listitem>
- <para>
- Man <emphasis>kann</emphasis> Zeilen spezifizieren die Ausdrücke innerhalb
- der ausgewählten Tabelle evaluieren. Trotzdem bedeutet das, das die
- zurückgegebene Zeile oder Zeilenset <property>readOnly</property> (nur
- lesbar) ist und nicht für save() Operationen verwendet werden kann. Eine
- <classname>Zend_Db_Table_Row</classname> mit <property>readOnly</property>
- Status wird eine Exception werfen wenn eine <code>save()</code> Operation
- versucht wird.
- </para>
- </listitem>
- <listitem>
- <para>
- Man <emphasis>kann</emphasis> JOIN Klauseln auf einer Auswahl erlauben um
- Mehrfach-Tabellen Lookups zu erlauben.
- </para>
- </listitem>
- <listitem>
- <para>
- Man <emphasis>kann keine</emphasis> Spalten von einer geJOINten Tabelle
- spezifizieren damit Sie in einer Zeile/Zeilenset zurückgegeben werden. Wenn
- das versucht wird, wird ein PHP Fehler getriggert. Das wurde getan um
- Sicherzustellen das die Integrität von <classname>Zend_Db_Table gewahrt
- bleibt</classname>. z.B. ein <classname>Zend_Db_Table_Row</classname> sollte
- nur Spalten referenzieren die von seiner Elterntabelle abgeleitet sind.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- <example id="zend.db.table.qry.rows.set.simple.usage.example">
- <title>Einfache Verwendung</title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- $select = $table->select();
- $select->where('bug_status = ?', 'NEW');
- $rows = $table->fetchAll($select);
- ]]></programlisting>
- </example>
- </para>
- <para>
- Flüssige Interfaces sind über alle Komponenten hinweg implementiert, sodas das zu
- einer mehr abgekürzteren Form umgeschrieben werden kann.
- </para>
- <para>
- <example id="zend.db.table.qry.rows.set.fluent.interface.example">
- <title>Example of fluent interface</title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- $rows =
- $table->fetchAll($table->select()->where('bug_status = ?', 'NEW'));
- ]]></programlisting>
- </example>
- </para>
- </sect3>
- <sect3 id="zend.db.table.fetch-all.usage">
- <title>Ein Set von Zeilen abfragen</title>
- <para>
- Ein Set von Zeilen kann abgefragt werden indem irgendein Kriterium verwendet wird,
- das anders als die Werte des Primärschlüssels sind, indem die
- <code>fetchAll()</code> Methode der Tabellen Klasse verwendet wird. Diese Methode
- gibt ein Objekt vom Typ <classname>Zend_Db_Table_Rowset_Abstract</classname> zurück.
- </para>
- <example id="zend.db.table.qry.rows.set.finding.row.example">
- <title>Beispiel für das Finden von Zeilen durch einen Ausdruck</title>
- <programlisting language="php"><![CDATA[
- $table = new Bugs();
- $select = $table->select()->where('bug_status = ?', 'NEW');
- $rows = $table->fetchAll($select);
- ]]></programlisting>
- </example>
- <para>
- Der <code>ORDER BY</code> kann auch ein Sortier-Kriterium übergeben werden, genauso
- wie auch Count und Offset Integer Werte, verwendet werden können damit die Abfrage
- ein spezielles Subset von Zeilen zurück gibt. Diese Werte werden in einer
- <code>LIMIT</code> Klausel verwendet oder in einer ähnlichen Logik für RDBMS Marken
- die die <code>LIMIT</code> Syntax nicht unterstützen.
- </para>
- <example id="zend.db.table.fetch-all.example2">
- <title>Beispiel für das Finden von Zeilen durch einen Ausdruck</title>
- <programlisting 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(array('bug_status = ?' => 'NEW'))
- ->order($order)
- ->limit($count, $offset);
- $rows = $table->fetchAll($select);
- ]]></programlisting>
- </example>
- <para>
- Alle diese Argumente sind optional. Wenn die ORDER Klausel unterdrückt wird, dann
- enthält das Ergebnis die Zeilen der Tabelle in einer unvorhersagbaren Reihenfolge.
- Wenn keine LIMIT Klausel gesetzt ist, dann wird jede Zeile dieser Tabelle
- zurückgegeben die der WHERE Klausen entspricht.
- </para>
- </sect3>
- <sect3 id="zend.db.table.advanced.usage">
- <title>Fortgeschrittene Verwendung</title>
- <para>
- Für speziellere und optimierte Ergebnisse, kann es gewünscht sein die Anzahl der
- zurückgegebenen Zeilen/Sets zu limitieren. Das kann durch die Übergabe einer FROM
- Klausel an das Select Objekt getan werden. Das erste Argument in der FROM Klausel
- ist identisch mit den des <classname>Zend_Db_Select</classname> Objekts wobei man
- zusätzlich eine Instanz von <classname>Zend_Db_Table_Abstract</classname> übergeben
- und damit den Tabellen Namen automatisch ermitteln lassen kann.
- </para>
- <para>
- <example id="zend.db.table.qry.rows.set.retrieving.a.example">
- <title>Spezielle Spalten erhalten</title>
- <programlisting 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>
- </para>
- <para>
- <important>
- <para>
- Das Rowset enthält Zeilen die trotzdem 'gültig' sind - sie enthalten bloß
- ein Subset der Spalten einer Tabelle. Wenn eine save() Methode auf dem Teil
- einer Zeile aufgerufen wird dann werden nur die vorhandenen Felder geändert.
- aufgerufen
- </para>
- </important>
- Es können Ausdrücke in einer FROM Klausel spezifiziert werden die dann als readOnly
- Zeile/Set zurückgegeben werden. In diesem Beispiel werden Zeilen von der Bugs
- Tabelle zurückgegeben die einen Bereich von Nummern neuer Bugs zeigen die von
- Individuen mitgeteilt wurden. Die GROUP Klausel ist zu beachten. Die 'count' Spalte
- wird der Zeile für Evaluation angefügt und es kann auch Sie zugegriffen werden wie
- wenn Sie ein Teil des Schemas wäre.
- </para>
- <para>
- <example id="zend.db.table.qry.rows.set.retrieving.b.example">
- <title>Ausdrücke als Spalten erhalten</title>
- <programlisting 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>
- Es kann auch ein Lookup als Teil der Abfrage verwendet werden um die Fetch
- Operation zu verfeinern. In diesem Beispiel wird die Accounts Tabelle als Teil
- einer Suche nach allen Bugs die von 'Bob' gemeldet wurden, abgefragt.
- </para>
- <para>
- <example id="zend.db.table.qry.rows.set.refine.example">
- <title>Beispiel für das Finden von Zeilen durch einen Ausdruck</title>
- <programlisting 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>
- <para>
- <classname>Zend_Db_Table_Select</classname> wird primär verwendet um zu verbinden
- und zu prüfen um die Kriterien für einen legalen SELECT Query sicherzustellen.
- Trotzdem gibt es viele Fälle in denen man die Flexibilität der
- <classname>Zend_Db_Table_Row</classname> benötigt und Zeilen nicht geschrieben oder
- gelöscht werden müssen. Für diesen speziellen Fall ist es möglich Zeilen/-sets durch
- die Übergabe eines false Wertes an setIntegrityCheck zu erhalten. Das resultierende
- Zeilen/-set wird als eine 'locked' Zeile zurückgegeben (das bedeutet das save(),
- delete() und jede andere Mothode die Felder setzt wird eine Ausnahme werfen).
- </para>
- <example id="zend.db.table.qry.rows.set.integrity.example">
- <title>
- Entfernen des Integritäts Checks von Zend_Db_Table_Select um geJOINte Zeilen zu
- erlauben
- </title>
- <programlisting 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 <code>fetchAll()</code> Methode sind.
- </para>
- <example id="zend.db.table.fetch-row.example1">
- <title>Beispiel für das Finden einer einzelnen Zeilen durch einen Ausdruck</title>
- <programlisting 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 <code>fetchRow()</code> PHP'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 <code>info()</code> Methode gibt eine Array Struktur mit
- Informationen über die Tabelle, Ihre Spalten und Primärschlüssel zurück, sowie andere
- Metadaten.
- </para>
- <example id="zend.db.table.info.example">
- <title>Beispiel für das Erhalten des Namens einer Tabelle</title>
- <programlisting 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 <code>info()</code> 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 <code>describeTable()</code> 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. Siese
- <xref linkend="zend.db.table.relationships.defining" />.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>dependentTables</emphasis> => ein Array von Klassennamen von
- Tabellen die diese Tabelle referenzieren. Siese
- <xref linkend="zend.db.table.relationships.defining" />.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>schema</emphasis> => der Name des Schemas (oder der
- Datenbank oder dem Tabellenraum) für diese Tabelle.
- </para>
- </listitem>
- </itemizedlist>
- </sect2>
- <sect2 id="zend.db.table.metadata.caching">
- <title>Tabellen Metadaten cachen</title>
- <para>
- Standardmäßig fragt <classname>Zend_Db_Table_Abstract</classname> die darunterliegende
- Datenbank für die <link linkend="zend.db.table.info">Metadaten der Tabelle</link> ab
- immer wenn diese diese Daten benötigt werden um Tabellenoperationen durchzuführen. Das
- Tableobjekt holt die Metadaten der Tabelle von der Datenbank indem es die
- <code>describeTable()</code> Methode des Adapters verwendet. Operationen die diese
- Einsicht benötigten sind:
- </para>
- <itemizedlist>
- <listitem><para><code>insert()</code></para></listitem>
- <listitem><para><code>find()</code></para></listitem>
- <listitem><para><code>info()</code></para></listitem>
- </itemizedlist>
- <para>
- In einigen Fällen, speziell wenn viele Table Objekte auf der gleichen Datenbanktabelle
- instanziert werden kann das Abfragen der Datenbank nach den Metadaten der Tabelle für
- jede Instanz unerwünscht sein wegen der Geschwindigkeit. In solchen Fällen, können
- Benutzer davon profitieren das die Metadaten der Tabelle, die von der Datenbank
- empfangen werden, gecached werden.
- </para>
- <para>
- Es gibt zwei grundsätzliche Wege bei denen ein Benutzer Vorteile davon haben kann wenn
- die Metadaten der Tabelle gecached werden:
- <itemizedlist>
- <listitem>
- <para>
- <emphasis>Aufruf von
- <classname>Zend_Db_Table_Abstract::setDefaultMetadataCache()</classname></emphasis>
- - Das erlaubt es Entwicklern das Standardcacheobjekt zu setzen das für alle
- Tabellenklassen verwendet werden soll.
- </para>
- </listitem>
- <listitem>
- <para>
- <emphasis>Konfigurieren von
- <classname>Zend_Db_Table_Abstract::__construct()</classname></emphasis> -
- Das erlaubt es Entwicklern das Cacheobjekt zu setzen das für eine spezielle
- Instanz der Tabellenklasse verwendet werden soll.
- </para>
- </listitem>
- </itemizedlist>
- In beiden Fällen muß die Spezifikation des Caches entweder <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 fpr die Metadaten
- $bugs = new Bugs();
- ]]></programlisting>
- </example>
- <example id="zend.db.table.metadata.caching-instance">
- <title>Einen Metadaten Cache für ein spezielles Tabellenobjekt verwenden</title>
- <para>
- Der folgende Code demonstriert wie ein Cache für Metadaten für eine spezielle
- Instanz eines Tabellenobjektes gesetzt werden kann:
- </para>
- <programlisting 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 describeTable() Methode des Adapters zurückgegeben
- wird, ein Array ist, muß sichergestellt werden das die
- <code>automatic_serialization</code> Option für das
- <classname>Zend_Cache_Core</classname> Frontend auf <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
- <code>metadataCacheInClass</code> 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 das 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 <code>'rowClass'</code>
- und <code>'rowsetClass'</code>. Die Namen der Klassen müssen spezifiziert werden
- indem Strings verwendet werden.
- </para>
- <example id="zend.db.table.extending.row-rowset.example">
- <title>
- Beispiel dafür wie die Zeilen und Rowset Klassen spezifiziert werden können
- </title>
- <programlisting 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 <code>setRowClass()</code> und
- <code>setRowsetClass()</code> Methoden spezifiziert werden. Das entspricht den
- Zeilen und Rowsets die nachfolgend erstellt werden; es ändert aber nicht die Klasse
- von Zeilen- oder Rowsetobjekten die bereits davor erstellt wurden.
- </para>
- <example id="zend.db.table.extending.row-rowset.example2">
- <title>Beispiel für das Ändern von Zeilen und Rowset Klassen</title>
- <programlisting 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
- <xref linkend="zend.db.table.row" /> und <xref linkend="zend.db.table.rowset" />.
- </para>
- </sect3>
- <sect3 id="zend.db.table.extending.insert-update">
- <title>Selbst definierte Logik für das Einfügen, Aktualisieren und Löschen</title>
- <para>
- Die <code>insert()</code> und <code>update()</code> Methoden in der Table Klasse
- können überschrieben werden. Das bietet die Möglichkeit eigenen Code einzufügen der
- ausgeführt wird bevor die Datenbank Operation durchgeführt wird. Es muß
- sichergestellt werden das die Methode der Elternklasse aufgerufen wird wenn man
- fertig ist.
- </para>
- <example id="zend.db.table.extending.insert-update.example">
- <title>Eigene Logik um Zeitstempel zu managen</title>
- <programlisting 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 <code>delete()</code> Methode kann überschrieben werden.
- </para>
- </sect3>
- <sect3 id="zend.db.table.extending.finders">
- <title>Eigene Such Methoden in Zend_Db_Table definieren</title>
- <para>
- Es können eigene Abfrage Methoden in der Table Klasse implementiert werden, wenn oft
- die Notwendigkeit besteht Abragen mit speziellen Kriterien auf der Table Klasse
- durchzuführen. Die meisten Abfragen können mit <code>fetchAll()</code> geschrieben
- werden, das bedeutet aber das Code dupliziert werden muß um Abfragekonditionen zu
- formen die Abfrage in verschiedenen Orten der Anwendung auszuführen. Hierfür kann es
- nützlich sein eine Methode in der Table Klasse zu definieren um oft benutzte
- Abfragen an dieser Tabelle durchzuführen.
- </para>
- <example id="zend.db.table.extending.finders.example">
- <title>Eigene Methode um Fehler durch den Status zu finden</title>
- <programlisting 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
- RDBMS, durch eine Stringumwandlung die <emphasis>Inflection</emphasis> (Beugung)
- genannt wird, entspricht.
- </para>
- <para>
- Wenn zum Beispiel der Name der Table Klasse "<code>BugsProducts</code>" ist, würde
- Sie der physikalischen Tabelle in der Datenbank entsprechen die
- "<code>bugs_products</code>" heißt, wenn die explizite Definition der
- <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 SQL Identifizierer exakt so wie Sie in der Datenbank vorhanden
- sind, macht <classname>Zend_Db_Table_Abstract</classname> sowohl einfacher als auch
- flexibler.
- </para>
- <para>
- Wenn man es vorzieht Beugung zu verwenden, muß die Transformation selbst durch das
- Überschreiben der <code>_setupTableName()</code> Methode in der eigenen
- Tabellenklasse implementiert werden. Ein Weg um das zu tun ist die Definition einer
- abstrakten Klase die <classname>Zend_Db_Table_Abstract</classname> erweitert. Der
- Rest der eigenen Klassen erweitert dann die eigene neue abstrakte Klasse.
- </para>
- <example id="zend.db.table.extending.inflection.example">
- <title>Beispiel einer abstrakten Tabellenklasse die Beugung implementiert</title>
- <programlisting 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>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|