Zend_Db_Table_Rowset.xml 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- EN-Revision: 15851 -->
  3. <!-- Reviewed: no -->
  4. <sect1 id="zend.db.table.rowset">
  5. <title>Zend_Db_Table_Rowset</title>
  6. <sect2 id="zend.db.table.rowset.introduction">
  7. <title>Einführung</title>
  8. <para>
  9. Wenn eine Datenbankabfrage über eine Tabellenklasse ausgeführt wird, genauer über deren
  10. Methoden <code>find()</code> und <code>fetchAll()</code>, wird das Ergebnis als Objekt
  11. vom Typ <classname>Zend_Db_Table_Rowset_Abstract</classname> zurückgegeben. Ein
  12. Zeilensatz enthält eine Sammlung von
  13. <classname>Zend_Db_Table_Row_Abstract</classname>-Objekten. Das Zeilensatz-Objekt
  14. implementiert das <code>Iterator</code>-Interface, sodass es auch einfach via
  15. <code>foreach</code> durchgegangen werden kann und Lese- und Schreibzugriff auf die
  16. einzelnen Zeilen möglich ist.
  17. </para>
  18. </sect2>
  19. <sect2 id="zend.db.table.rowset.fetch">
  20. <title>Einen Zeilensatz lesen</title>
  21. <para>
  22. <classname>Zend_Db_Table_Abstract</classname> bietet die Methoden <code>find()</code>
  23. und <code>fetchAll()</code>, die beide ein Objekt vom Typ
  24. <classname>Zend_Db_Table_Rowset_Abstract</classname> zurückgeben.
  25. </para>
  26. <example id="zend.db.table.rowset.fetch.example">
  27. <title>Einen Zeilensatz lesen</title>
  28. <programlisting language="php"><![CDATA[
  29. $bugs = new Bugs();
  30. $rowset = $bugs->fetchAll("bug_status = 'NEW'");
  31. ]]></programlisting>
  32. </example>
  33. </sect2>
  34. <sect2 id="zend.db.table.rowset.rows">
  35. <title>Zeilen aus einem Zeilensatz auslesen</title>
  36. <para>
  37. Der Zeilensatz selber ist normalerweise weniger interessant als die Zeilen, die er
  38. enthält. Dieser Abschnitt zeigt, wie die Zeilen, die im Zeilensatz enthalten sind,
  39. auslesbar sind.
  40. </para>
  41. <para>
  42. Eine normale Abfrage gibt null Zeilen zurück, wenn keine Zeilen in der Datenbank die
  43. Bedingungen der Abfrage erfüllt. Daher kann eine Zeilensatz-Objekt auch null
  44. Zeilenobjekte enthalten. Weil <classname>Zend_Db_Table_Rowset_Abstract</classname> auch
  45. das Interface <code>Countable</code> (dt.: Zählbar) implementiert, kann die Funktion
  46. count() genutzt werden, um die Anzahl der Zeilen im Zeilensatz zu erhalten.
  47. </para>
  48. <example id="zend.db.table.rowset.rows.counting.example">
  49. <title>Zeilen in einem Zeilensatz zählen</title>
  50. <programlisting language="php"><![CDATA[
  51. $rowset = $bugs->fetchAll("bug_status = 'FIXED'");
  52. $rowCount = count($rowset);
  53. if ($rowCount > 0) {
  54. echo "$rowCount Zeilen gefunden!";
  55. } else {
  56. echo 'keine Zeilen für die Abfrage gefunden.';
  57. }
  58. ]]></programlisting>
  59. </example>
  60. <example id="zend.db.table.rowset.rows.current.example">
  61. <title>Eine einzelne Zeile aus einem Zeilensatz auslesen</title>
  62. <para>
  63. Die einfachste Art, eine Zeile aus einem Zeilensatz auszulesen, ist die Methode
  64. <code>current()</code>. Diese ist vor allem dann nützlich, wenn der Zeilensatz genau
  65. eine Zeile enthält.
  66. </para>
  67. <programlisting language="php"><![CDATA[
  68. $bugs = new Bugs();
  69. $rowset = $bugs->fetchAll("bug_id = 1");
  70. $row = $rowset->current();
  71. ]]></programlisting>
  72. </example>
  73. <para>
  74. Wenn der Zeilensatz keine Zeilen enthält, gibt <code>current()</code> den Wert
  75. <constant>NULL</constant> zurück.
  76. </para>
  77. <example id="zend.db.table.rowset.rows.iterate.example">
  78. <title>Einen Zeilensatz durchlaufen</title>
  79. <para>
  80. Objekte, die von <classname>Zend_Db_Table_Rowset_Abstract</classname> abstammen,
  81. implementieren das <code>SeekableIterator</code> Interface, was bedeutet, dass es
  82. mit <code>foreach</code> durchlaufen werden kann. Jeder Wert, der auf diesem Weg
  83. zurückgegeben wird, ist ein
  84. <classname>Zend_Db_Table_Row_Abstract</classname>-Objekt, das zu einem Eintrag in
  85. der Tabelle gehört.
  86. </para>
  87. <programlisting language="php"><![CDATA[
  88. $bugs = new Bugs();
  89. // Alle Zeilen aus der Tabelle lesen
  90. $rowset = $bugs->fetchAll();
  91. foreach ($rowset as $row) {
  92. // Ausgabe: 'Zend_Db_Table_Row' oder ähnlich,
  93. // je nach benutzter Zeilenklasse
  94. echo get_class($row) . "\n";
  95. // Spalte einer Zeile auslesen
  96. $status = $row->bug_status;
  97. // eine Spalte der aktuellen Zeile modifizieren
  98. $row->assigned_to = 'mmouse';
  99. // Änderung in der Datenbank speichern
  100. $row->save();
  101. }
  102. ]]></programlisting>
  103. </example>
  104. <example id="zend.db.table.rowset.rows.seek.example">
  105. <title>Eine bekannte Position in einem Rowset suchen</title>
  106. <para>
  107. <code>SeekableIterator</code> erlaubt es eine Position zu suchen auf die der
  108. Iterator springen soll. Hierfür kann einfach die <code>seek()</code> Methode
  109. verwendet werden. Es kann ein Integer übergeben werden die der Nummer der Zeile
  110. repräsentiert auf die das Rowset als nächstes zeigen soll, wobei man nicht
  111. vergessen sollte das der Index mit 0 beginnt. Wenn der Index falsch ist, z.b. nicht
  112. existiert, wird eine Ausnahme geworfen. Man sollte <code>count()</code>
  113. verwenden um die Anzahl an Ergebnissen zu prüfen bevor eine Position gesucht wird.
  114. </para>
  115. <programlisting language="php"><![CDATA[
  116. $bugs = new Bugs();
  117. // Alle Einträge von der Tabelle holen
  118. $rowset = $bugs->fetchAll();
  119. // Den Iterator zum 9ten Element bringen (null ist das erste Element) :
  120. $rowset->seek(8);
  121. // es empfangen
  122. $row9 = $rowset->current();
  123. // und es verwenden
  124. $row9->assigned_to = 'mmouse';
  125. $row9->save();
  126. ]]></programlisting>
  127. </example>
  128. <para>
  129. <code>getRow()</code> erlaubt es eine spezielle Zeile im Rowset zu erhalten wenn
  130. dessen Position bekannt ist; trotzdem sollte nicht vergessen werden dass die
  131. Position mit dem Index null beginnt. Der erste Parameter für <code>getRow()</code>
  132. ist ein Integer für die gewünschte Position. Der zweite optionale Parameter ist ein
  133. Boolean; Es teilt dem Rowset Iterator mit ob er zur gleichen Zeit diese Position
  134. suchen muss, oder nicht (standard ist nicht). Diese Methode gibt standardmäßig ein
  135. <classname>Zend_Db_Table_Row</classname> Objekt zurück. Wenn die angefragte Position
  136. nicht existiert wird eine Ausnahme geworfen. Hier ist ein Beispiel:
  137. </para>
  138. <programlisting language="php"><![CDATA[
  139. $bugs = new Bugs();
  140. // Alle Einträge von der Tabelle holen
  141. $rowset = $bugs->fetchAll();
  142. // Sofort das 9te Element holen:
  143. $row9->getRow(8);
  144. // und es verwenden:
  145. $row9->assigned_to = 'mmouse';
  146. $row9->save();
  147. ]]></programlisting>
  148. <para>
  149. Sobald der Zugriff auf ein Zeilenobjekt besteht, kann dieses mit den Methoden
  150. manipuliert werden, die in <xref linkend="zend.db.table.row" /> beschrieben werden.
  151. </para>
  152. </sect2>
  153. <sect2 id="zend.db.table.rowset.to-array">
  154. <title>Einen Zeilensatz als Array lesen</title>
  155. <para>
  156. Auf die gesamten Daten in einem Zeilensatz kann mithilfe der Methode
  157. <code>toArray()</code> des Zeilensatz-Objekts auch als Array zugegriffen werden. Diese
  158. Methode gibt ein Array mit einem Eintrag je Zeile zurück. Jeder dieser Einträge ist ein
  159. assoziatives Array mit Spaltennamen als Schlüsseln und deren Daten als Werten.
  160. </para>
  161. <example id="zend.db.table.rowset.to-array.example">
  162. <title>Benutzung von toArray()</title>
  163. <programlisting language="php"><![CDATA[
  164. $bugs = new Bugs();
  165. $rowset = $bugs->fetchAll();
  166. $rowsetArray = $rowset->toArray();
  167. $rowCount = 1;
  168. foreach ($rowsetArray as $rowArray) {
  169. echo "Zeile #$rowCount:\n";
  170. foreach ($rowArray as $column => $value) {
  171. echo "\t$column => $value\n";
  172. }
  173. ++$rowCount;
  174. echo "\n";
  175. }
  176. ]]></programlisting>
  177. </example>
  178. <para>
  179. Das Array, das von <code>toArray()</code>zurückgegeben wird, ist nicht update-fähig.
  180. Die Werte des Arrays können wie bei jedem Array modifiziert werden, aber Änderungen an
  181. diesem Array werden nicht direkt in der Datenbank gespeichert.
  182. </para>
  183. </sect2>
  184. <sect2 id="zend.db.table.rowset.serialize">
  185. <title>Einen Zeilensatz serialisieren / deserialisieren</title>
  186. <para>
  187. Objekte vom Typ <classname>Zend_Db_Table_Rowset_Abstract</classname> sind serialisierbar
  188. auf eine ähnliche Art, wie auch einzelne Zeilen-Objekte serialisierbar und
  189. deserialisierbar sind.
  190. </para>
  191. <example id="zend.db.table.rowset.serialize.example.serialize">
  192. <title>Einen Zeilensatz serialisieren</title>
  193. <para>
  194. PHPs <code>serialize()</code>-Funktion wird genutzt, um einen Byte-Stream zu
  195. erzeugen. Dieser repräsentiert das Zeilensatz-Objekt.
  196. </para>
  197. <programlisting language="php"><![CDATA[
  198. $bugs = new Bugs();
  199. $rowset = $bugs->fetchAll();
  200. // Objekt serialisieren
  201. $serializedRowset = serialize($rowset);
  202. // Jetzt kann $serializedRowset bspw.
  203. // in einer Datei gespeichert werden
  204. ]]></programlisting>
  205. </example>
  206. <example id="zend.db.table.rowset.serialize.example.unserialize">
  207. <title>Einen Zeilensatz deserialisieren</title>
  208. <para>
  209. PHPs <code>unserialize()</code> stellt aus einer Zeichenkette mit einem Byte-Stream
  210. ein Objekt wieder her. Die Funktion gibt das originale Objekt zurück.
  211. </para>
  212. <para>
  213. Bitte beachten: Das zurückgegebene Zeilensatz-Objekt ist
  214. <emphasis>nicht mit der Datenbank verbunden</emphasis>. Das Zeilensatz-Objekt kann
  215. durchlaufen werden und die Zeilenobjekte können gelesen werden, aber es können keine
  216. Zeilenwerte verändert oder andere Operationen ausgeführt werden, die eine
  217. Datenbankverbindung benötigen (beispielsweise Abfragen auf verwandte Tabellen).
  218. </para>
  219. <programlisting language="php"><![CDATA[
  220. $rowsetDisconnected = unserialize($serializedRowset);
  221. // Jetzt können Objekt-Methoden und -Eigenschaften genutzt werden,
  222. // aber nur lesend.
  223. $row = $rowsetDisconnected->current();
  224. echo $row->bug_description;
  225. ]]></programlisting>
  226. </example>
  227. <note>
  228. <title>Warum werden Zeilensatz-Objekte unverbunden deserialisiert?</title>
  229. <para>
  230. Ein serialisiertes Objekt ist eine Zeichenkette, die lesbar für jeden ist, dem sie
  231. vorliegt. Es könnte ein Sicherheitsrisiko sein, Parameter wie Datenbank-Loginname
  232. und -Passwort in simplem, unverschlüsseltem Text abzulegen. Es ist nicht
  233. wünschenswert, solche Daten in einer Textdatei abzulegen, die nicht geschützt ist,
  234. oder sie in einer E-Mail oder einem anderen Medium zu versenden, das leicht von
  235. potentiellen Angreifern lesbar ist. Der Leser des serialisierten Objekts sollte es
  236. nicht benutzen können, um Zugriff zur Datenbank zu erhalten, ohne richtige
  237. Logindaten zu kennen.
  238. </para>
  239. </note>
  240. <para>
  241. Ein nicht verbundenes Zeilensatz-Objekt kann mithilfe der Methode
  242. <code>setTable()</code> reaktiviert werden. Das Argument dieser Methode ist ein valides
  243. <classname>Zend_Db_Table_Abstract</classname>-Objekt,
  244. das vom Benutzer erstellt wird. Für das Erstellen eines Tabellenobjekts wird eine aktive
  245. Datenbankverbindung benötigt, also wird, indem die Tabelle wieder mit dem Zeilenobjekt
  246. verknüpft wird, auch der Datenbankzugriff wiederhergestellt. Ab diesem Zeitpunkt können
  247. Werte in den enthaltenen Zeilenobjekten wieder verändert und in der Datenbank
  248. gespeichert werden.
  249. </para>
  250. <example id="zend.db.table.rowset.serialize.example.set-table">
  251. <title>Einen Zeilensatz als Live-Daten reaktivieren</title>
  252. <programlisting language="php"><![CDATA[
  253. $rowset = unserialize($serializedRowset);
  254. $bugs = new Bugs();
  255. // Den Zeilensatz wieder mit einer Tabelle
  256. // und damit mit einer aktiven Datenbankverbindung verknüpfen
  257. $rowset->setTable($bugs);
  258. $row = $rowset->current();
  259. // Jetzt können wieder Werte geändert und danach gespeichert werden
  260. $row->bug_status = 'FIXED';
  261. $row->save();
  262. ]]></programlisting>
  263. </example>
  264. <para>
  265. Wenn ein Zeilensatz mit <code>setTable()</code> reaktiviert wird,
  266. reaktiviert das auch alle enthaltenen Zeilen-Objekte.
  267. </para>
  268. </sect2>
  269. <sect2 id="zend.db.table.rowset.extending">
  270. <title>Die Zeilensatz-Klasse erweitern</title>
  271. <para>
  272. Es können auch alternative Klassen für Zeilensätze benutzt werden, wenn diese
  273. <classname>Zend_Db_Table_Rowset_Abstract</classname> erweitern. Der Name der eigenen
  274. Zeilensatz-Klasse wird entweder in der geschützten Tabellenklassen-Eigenschaft
  275. <varname>$_rowsetClass</varname> oder als Teil des Array-Arguments des Konstruktors eines
  276. Tabellenobjekts übergeben.
  277. </para>
  278. <example id="zend.db.table.rowset.extending.example">
  279. <title>Eine eigene Zeilensatz-Klasse angeben</title>
  280. <programlisting language="php"><![CDATA[
  281. class MyRowset extends Zend_Db_Table_Rowset_Abstract
  282. {
  283. // ...Anpassungen
  284. }
  285. // Eine eigene Zeilensatz-Klasse angeben, die standardmäßig
  286. // in allen Instanzen der Tabellenklasse benutzt wird.
  287. class Products extends Zend_Db_Table_Abstract
  288. {
  289. protected $_name = 'products';
  290. protected $_rowsetClass = 'MyRowset';
  291. }
  292. // Oder eine eigene Zeilensatz-Klasse angeben, die in einer
  293. // Instanz einer Tabellenklasse benutzt wird
  294. $bugs = new Bugs(array('rowsetClass' => 'MyRowset'));
  295. ]]></programlisting>
  296. </example>
  297. <para>
  298. Typischerweise reicht die Standardklasse <classname>Zend_Db_Rowset</classname> für die
  299. meisten Benutzungsfälle aus. Trotzdem könnte es nützlich sein, neue Logik in einen
  300. Zeilensatz einzubauen, die für eine bestimmte Tabelle nötig ist. Beispielsweise könnte
  301. eine neue Methode einen Durchschnitt aller Zeilen im Zeilensatz errechnen.
  302. </para>
  303. <example id="zend.db.table.rowset.extending.example-aggregate">
  304. <title>Eine Zeilensatz-Klasse mit einer neuen Methode</title>
  305. <programlisting language="php"><![CDATA[
  306. class MyBugsRowset extends Zend_Db_Table_Rowset_Abstract
  307. {
  308. /**
  309. * Suche nach der Zeile im Zeilensatz, deren
  310. * 'updated_at'-Spalte den größten Wert hat.
  311. */
  312. public function getLatestUpdatedRow()
  313. {
  314. $max_updated_at = 0;
  315. $latestRow = null;
  316. foreach ($this as $row) {
  317. if ($row->updated_at > $max_updated_at) {
  318. $latestRow = $row;
  319. }
  320. }
  321. return $latestRow;
  322. }
  323. }
  324. class Bugs extends Zend_Db_Table_Abstract
  325. {
  326. protected $_name = 'bugs';
  327. protected $_rowsetClass = 'MyBugsRowset';
  328. }
  329. ]]></programlisting>
  330. </example>
  331. </sect2>
  332. </sect1>
  333. <!--
  334. vim:se ts=4 sw=4 et:
  335. -->