Zend_Db_Table_Rowset.xml 13 KB

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