Zend_Db_Table_Rowset.xml 15 KB

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