2
0

Zend_Db_Table_Rowset.xml 16 KB

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