Zend_Db_Table_Rowset.xml 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!-- EN-Revision: 13846 -->
  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>Introduction</title>
  8. <para>Lorsque vous effectuez une requête avec une classe de Table en utilisant <code>find()</code> ou
  9. <code>fetchAll()</code> , le résultat retourné est alors un objet de type
  10. <classname>Zend_Db_Table_Rowset_Abstract</classname>. Un Rowset est un conteneur d'objets descendants de
  11. <classname>Zend_Db_Table_Row_Abstract</classname>. Vous pouvez itérer à travers ce conteneur et accéder aux objet Row
  12. individuellement, en lecture ou écriture bien entendu.</para>
  13. </sect2>
  14. <sect2 id="zend.db.table.rowset.fetch">
  15. <title>Récupérer un Rowset</title>
  16. <para><classname>Zend_Db_Table_Abstract</classname> possède des méthodes <code>find()</code> et <code>fetchAll()</code>,
  17. chacune retourne un objet de type <classname>Zend_Db_Table_Rowset_Abstract</classname>.</para>
  18. <example id="zend.db.table.rowset.fetch.example">
  19. <title>Exemple de récupération d'un rowset</title>
  20. <programlisting role="php"><![CDATA[
  21. $bugs = new Bugs();
  22. $rowset = $bugs->fetchAll("bug_status = 'NEW'");
  23. ]]></programlisting>
  24. </example>
  25. </sect2>
  26. <sect2 id="zend.db.table.rowset.rows">
  27. <title>Atteindre les Rows depuis un Rowset</title>
  28. <para>L'objet Rowset en lui-même n'est pas très intéressant au regard des objets Rows qu'il contient, qui eux,
  29. le sont bien plus.</para>
  30. <para>Un requête légitime peut retourner zéro enregistrement, donc zéro Rows. De ce fait, un objet Rowset peut
  31. contenir zéro objet Row. Comme <classname>Zend_Db_Table_Rowset_Abstract</classname> implémente l'interface
  32. <code>Countable</code>, vous pouvez utiliser la fonction PHP <code>count()</code> dessus, pour compter les Rows
  33. qu'il contient.</para>
  34. <example id="zend.db.table.rowset.rows.counting.example">
  35. <title>Compter les Rows dans un Rowset</title>
  36. <programlisting role="php"><![CDATA[
  37. $rowset = $bugs->fetchAll("bug_status = 'FIXED'");
  38. $rowCount = count($rowset);
  39. if ($rowCount > 0) {
  40. echo "$rowCount rows trouvés";
  41. } else {
  42. echo 'Pas de rows pour cette requête';
  43. }
  44. ]]></programlisting>
  45. </example>
  46. <example id="zend.db.table.rowset.rows.current.example">
  47. <title>Lecture d'un simple Row depuis un Rowset</title>
  48. <para>La façon la plus simple d'accéder à un Row depuis l'objet Rowset est d'utiliser la méthode
  49. <code>current()</code>. C'est tout à fait adapté lorsque le Rowset ne contient qu'un résultat (Row).</para>
  50. <programlisting role="php"><![CDATA[
  51. $bugs = new Bugs();
  52. $rowset = $bugs->fetchAll("bug_id = 1");
  53. $row = $rowset->current();
  54. ]]></programlisting>
  55. </example>
  56. <para>Si le Rowset ne contient aucun Row, <code>current()</code> retourne <code>null</code>.</para>
  57. <example id="zend.db.table.rowset.rows.iterate.example">
  58. <title>Itération à travers un Rowset</title>
  59. <para>Les objets descendants de <classname>Zend_Db_Table_Rowset_Abstract</classname> implémentent l'interface
  60. <code>Iterator</code>, ce qui veut dire qu'ils peuvent être utilisés dans la structure PHP
  61. <code>foreach</code>. Chaque valeur récupérée représente alors un objet de
  62. <classname>Zend_Db_Table_Row_Abstract</classname> qui correspond à un enregistrement dans la table.</para>
  63. <programlisting role="php"><![CDATA[
  64. $bugs = new Bugs();
  65. // récupère tous les enregistrements de la table
  66. $rowset = $bugs->fetchAll();
  67. foreach ($rowset as $row) {
  68. // affiche 'Zend_Db_Table_Row' par défaut
  69. echo get_class($row) . "\n";
  70. // lit une colonne dans le résultat Row
  71. $status = $row->bug_status;
  72. // modifie une colonne dans le résultat courant
  73. $row->assigned_to = 'mmouse';
  74. // Enregistre en base de données
  75. $row->save();
  76. }
  77. ]]></programlisting>
  78. </example>
  79. <example id="zend.db.table.rowset.rows.seek.example">
  80. <title>Déplacement vers une position précise dans le Rowset</title>
  81. <para><code>SeekableIterator</code> vous permet de vus déplacer à une position précise dans l'itérateur.
  82. Utilisez pour ceci la méthode <code>seek()</code>. Elle prend en paramètre un entier représentant le numéro
  83. de la position désirée. N'oubliez pas que le premier enregistrement est stocké à la position zéro. Si vous
  84. spécifiez une position qui n'existe pas, une exception sera levée. Vous devriez utiliser
  85. <code>count()</code> pour vérifier le nombre d'enregistrements Rows présents.</para>
  86. <programlisting role="php"><![CDATA[
  87. $bugs = new Bugs();
  88. // récupère tous les enregistrements de la table
  89. $rowset = $bugs->fetchAll();
  90. // Déplace l'itérateur à l'enregistrement 8 (le neuvième donc) :
  91. $rowset->seek(8);
  92. // récupèration de cet enregistrement
  93. $row9 = $rowset->current();
  94. // et utilisation
  95. $row9->assigned_to = 'mmouse';
  96. $row9->save();
  97. ]]></programlisting>
  98. </example>
  99. <para><code>getRow()</code> permet de retourner directement un enregistrement en fonction de sa position dans
  100. l'itérateur Rowset. Le premier paramètre est un entier représentant cette position. Le second paramètre est
  101. optionnel, et indique si oui ou non l'itérateur doit rester sur cette position, après avoir retourné le Row
  102. correspondant. Par défaut, il est à <code>false</code>. Cette méthode retourne donc un objet
  103. <classname>Zend_Db_Table_Row</classname>. Si la position demandée n'existe pas, une exception est levée :</para>
  104. <programlisting role="php"><![CDATA[
  105. $bugs = new Bugs();
  106. // récupère tous les enregistrements de la table
  107. $rowset = $bugs->fetchAll();
  108. // récupère le neuvième enregistrement immédiatement
  109. $row9->getRow(8);
  110. // utilisation de l'enregistrement récupéré :
  111. $row9->assigned_to = 'mmouse';
  112. $row9->save();
  113. ]]></programlisting>
  114. <para>Dès que vous avez accès à un objet individuel Row, vous pouvez le piloter comme présenté dans la section
  115. <xref linkend="zend.db.table.row" />.</para>
  116. </sect2>
  117. <sect2 id="zend.db.table.rowset.to-array">
  118. <title>Récupérer un Rowset en tant que tableau (Array)</title>
  119. <para>Vous pouvez accéder à toutes les données d'un Rowset au moyen d'un tableau PHP avec la méthode
  120. <code>toArray()</code>. Ce tableau possède deux dimensions. Chaque entrée du tableau représente un tableau de
  121. l'objet Row. Les clés sont les noms des champs, et les valeurs leurs valeurs.</para>
  122. <example id="zend.db.table.rowset.to-array.example">
  123. <title>Utiliser <code>toArray()</code></title>
  124. <programlisting role="php"><![CDATA[
  125. $bugs = new Bugs();
  126. $rowset = $bugs->fetchAll();
  127. $rowsetArray = $rowset->toArray();
  128. $rowCount = 1;
  129. foreach ($rowsetArray as $rowArray) {
  130. echo "row #$rowCount:\n";
  131. foreach ($rowArray as $column => $value) {
  132. echo "\t$column => $value\n";
  133. }
  134. ++$rowCount;
  135. echo "\n";
  136. }
  137. ]]></programlisting>
  138. </example>
  139. <para>Le tableau retourné par <code>toArray()</code> n'est pas une référence. Le modifier ne modifiera en aucun
  140. cas les données réelles dans la base de données.</para>
  141. </sect2>
  142. <sect2 id="zend.db.table.rowset.serialize">
  143. <title>Sérialisation et Désérialisation d'un Rowset</title>
  144. <para>Les objets de type <classname>Zend_Db_Table_Rowset_Abstract</classname> sont sérialisables. De la même manière que
  145. vous sérialisez un objet Row individuel, le Rowset est sérialisable et désérialisable.</para>
  146. <example id="zend.db.table.rowset.serialize.example.serialize">
  147. <title>Sérialiser d'un Rowset</title>
  148. <para>Utilisez simplement la fonction PHP <code>serialize()</code> pour créer une chaîne de caractères
  149. représentant votre objet Rowset.</para>
  150. <programlisting role="php"><![CDATA[
  151. $bugs = new Bugs();
  152. $rowset = $bugs->fetchAll();
  153. // Convertit l'objet en sa forme sérialisée
  154. $serializedRowset = serialize($rowset);
  155. // Maintenant vous pouvez écrire $serializedRowset
  156. // dans un fichier, etc.
  157. ]]></programlisting>
  158. </example>
  159. <example id="zend.db.table.rowset.serialize.example.unserialize">
  160. <title>Désérialisation d'un objet Rowset sérialisé</title>
  161. <para>Utilisez simplement la fonction PHP <code>unserialize()</code>.</para>
  162. <para>Notez que l'objet retourné fonctionne alors en mode <emphasis>déconnecté</emphasis>. Vous pouvez
  163. itérer à travers, et lire les objets Row qu'il contient, mais vous ne pouvez plus faire intervenir la base
  164. de données, ni changer de valeurs dans les Rows.</para>
  165. <programlisting role="php"><![CDATA[
  166. $rowsetDisconnected = unserialize($serializedRowset);
  167. // Maintenant vous pouvez utiliser l'objet, mais en lecture seule
  168. $row = $rowsetDisconnected->current();
  169. echo $row->bug_description;
  170. ]]></programlisting>
  171. </example>
  172. <note>
  173. <title>Pourquoi ce mode déconnecté imposé ?</title>
  174. <para>Un objet sérialisé est une chaîne de caractère, humainement visible. Il est donc peut sécurisé d'y
  175. laisser un mot de passe vers un serveur de base de données. Le lecteur d'un objet Rowset sérialisé ne
  176. devrait pas pouvoir accéder à la base de données. De plus, une connexion à une base de données est un type
  177. non sérialisable par PHP (ressource).</para>
  178. </note>
  179. <para>Il est bien entendu possible de reconnecter l'objet Rowset à la base de données, et plus précisément à la
  180. Table dont il fut issu. Utilisez la méthode <code>setTable()</code> et passez lui une instance héritant de
  181. <classname>Zend_Db_Table_Abstract</classname>. Une fois reconnecté, l'objet Rowset possède de nouveau un accès à la base
  182. de données, et n'est donc plus en mode lecture seule.</para>
  183. <example id="zend.db.table.rowset.serialize.example.set-table">
  184. <title>Réactivation d'un Rowset</title>
  185. <programlisting role="php"><![CDATA[
  186. $rowset = unserialize($serializedRowset);
  187. $bugs = new Bugs();
  188. // Reconnecte le rowset à une table, et par
  189. // conséquent, à la connexion vers la base de données active
  190. $rowset->setTable($bugs);
  191. $row = $rowset->current();
  192. // Maintenant vous pouvez modifier les objets Row et les sauvegarder
  193. $row->bug_status = 'FIXED';
  194. $row->save();
  195. ]]></programlisting>
  196. </example>
  197. <para>Réactiver un Rowset avec <code>setTable()</code> réactive tous les Rows le composant.</para>
  198. </sect2>
  199. <sect2 id="zend.db.table.rowset.extending">
  200. <title>Étendre la classe Rowset</title>
  201. <para>Vous pouvez utilisez votre propre classe étendant <classname>Zend_Db_Table_Rowset_Abstract</classname>. Spécifiez
  202. votre classe dans la propriété protégée <code>$_rowsetClass</code> de la classe de votre Table, ou dans le
  203. tableau du constructeur de l'objet Table.</para>
  204. <example id="zend.db.table.rowset.extending.example">
  205. <title>Spécifier sa propre classe de Rowset</title>
  206. <programlisting role="php"><![CDATA[
  207. class MyRowset extends Zend_Db_Table_Rowset_Abstract
  208. {
  209. // ...personnalisations
  210. }
  211. // Spécifie la classe de Rowset utilisée pour toutes les
  212. // instance de la classe de Table
  213. class Products extends Zend_Db_Table_Abstract
  214. {
  215. protected $_name = 'products';
  216. protected $_rowsetClass = 'MyRowset';
  217. }
  218. // Ou pour une classe de table spécifique, via son constructeur
  219. $bugs = new Bugs(array('rowsetClass' => 'MyRowset'));
  220. ]]></programlisting>
  221. </example>
  222. <para>En temps normal, la classe standard Zend_Db_Rowset est suffisante. Cependant, il peut être judicieux de
  223. rajouter de la logique dans son Rowset, pour une table précise. Par exemple, une nouvelle méthode pourrait
  224. effectuer des calculs.</para>
  225. <example id="zend.db.table.rowset.extending.example-aggregate">
  226. <title>Exemple d'une classe Rowset personnalisée avec une nouvelle méthode</title>
  227. <programlisting role="php"><![CDATA[
  228. class MyBugsRowset extends Zend_Db_Table_Rowset_Abstract
  229. {
  230. /**
  231. * Trouve les Rows dans le Rowset courant avec la plus grande
  232. * valeur pour la colonne 'updated_at'.
  233. */
  234. public function getLatestUpdatedRow()
  235. {
  236. $max_updated_at = 0;
  237. $latestRow = null;
  238. foreach ($this as $row) {
  239. if ($row->updated_at > $max_updated_at) {
  240. $latestRow = $row;
  241. }
  242. }
  243. return $latestRow;
  244. }
  245. }
  246. class Bugs extends Zend_Db_Table_Abstract
  247. {
  248. protected $_name = 'bugs';
  249. protected $_rowsetClass = 'MyBugsRowset';
  250. }
  251. ]]></programlisting>
  252. </example>
  253. </sect2>
  254. </sect1>