1 <?xml version="1.0" encoding="UTF-8"?>
3 <!-- EN-Revision: 20766 -->
4 <sect1 id="zend.db.table.rowset">
6 <title>Zend_Db_Table_Rowset</title>
8 <sect2 id="zend.db.table.rowset.introduction">
13 テーブルクラスに対して <methodname>find()</methodname>
14 あるいは <methodname>fetchAll()</methodname> メソッドでクエリを実行すると、
15 返される結果は <classname>Zend_Db_Table_Rowset_Abstract</classname> 型のオブジェクトとなります。
16 行セットには、<classname>Zend_Db_Table_Row_Abstract</classname> を継承したオブジェクトが含まれます。
17 行セットを使用して各行オブジェクトに対して順にアクセスし、
18 行のデータを読み込んだり変更したりできます。
23 <sect2 id="zend.db.table.rowset.fetch">
25 <title>行セットの取得</title>
28 <classname>Zend_Db_Table_Abstract</classname> には <methodname>find()</methodname> と
29 <methodname>fetchAll()</methodname> というメソッドがあります。
30 これらはどちらも <classname>Zend_Db_Table_Rowset_Abstract</classname> 型のオブジェクトを返します。
33 <example id="zend.db.table.rowset.fetch.example">
35 <title>行セットの取得の例</title>
37 <programlisting language="php"><![CDATA[
39 $rowset = $bugs->fetchAll("bug_status = 'NEW'");
46 <sect2 id="zend.db.table.rowset.rows">
48 <title>行セットからの行の取得</title>
51 通常は、行セットそのものよりもその中に含まれる行のほうが重要になります。
52 この節では、行セットを構成する行の情報を取得する方法について説明します。
56 正しい形式のクエリであっても、結果がゼロ行となることがありえます。
57 たとえば、抽出条件に一致する行がデータベース内に存在しない場合などです。
58 したがって、行セットオブジェクトの中身の行オブジェクトの個数がゼロになることもあります。
59 <classname>Zend_Db_Table_Rowset_Abstract</classname> は
60 <classname>Countable</classname> インターフェイスを実装しているので、
61 <methodname>count()</methodname> を使用すると行セット内の行の数を調べられます。
64 <example id="zend.db.table.rowset.rows.counting.example">
66 <title>行セット内の行の数を数える</title>
68 <programlisting language="php"><![CDATA[
69 $rowset = $bugs->fetchAll("bug_status = 'FIXED'");
71 $rowCount = count($rowset);
74 echo "見つかった行数は $rowCount です";
76 echo 'クエリにマッチする行がありません';
82 <example id="zend.db.table.rowset.rows.current.example">
84 <title>行セットからの単一の行の読み込み</title>
87 行セットから行にアクセスするための一番簡単な方法は
88 <methodname>current()</methodname> メソッドを使用することです。
89 これは、行セットに含まれる行数がひとつである場合に最適です。
92 <programlisting language="php"><![CDATA[
94 $rowset = $bugs->fetchAll("bug_id = 1");
95 $row = $rowset->current();
101 行セットに含まれる行数がゼロの場合、<methodname>current()</methodname>
102 が返す値は <acronym>PHP</acronym> の <constant>NULL</constant> 値となります。
105 <example id="zend.db.table.rowset.rows.iterate.example">
107 <title>行セットの順次処理</title>
110 <classname>Zend_Db_Table_Rowset_Abstract</classname> を継承したオブジェクトは
111 <classname>SeekableIterator</classname> インターフェイスを実装しています。つまり、
112 <methodname>foreach()</methodname> ループを使用できるということです。
113 これを使用して取得した個々の値は <classname>Zend_Db_Table_Row_Abstract</classname>
114 オブジェクトとなり、これがテーブルの各行に対応します。
117 <programlisting language="php"><![CDATA[
120 // テーブルのすべてのレコードを取得します
121 $rowset = $bugs->fetchAll();
123 foreach ($rowset as $row) {
125 // 出力は 'Zend_Db_Table_Row' あるいはそれに似たものとなります
126 echo get_class($row) . "\n";
129 $status = $row->bug_status;
132 $row->assigned_to = 'mmouse';
141 <example id="zend.db.table.rowset.rows.seek.example">
143 <title>行セット内の既知の位置への移動</title>
146 <classname>SeekableIterator</classname> は、
148 そのために使用するのが <methodname>seek()</methodname> メソッドです。
149 行番号を渡すと、行セット内のその次の位置に移動できます。
150 行番号は 0 から始まることに注意しましょう。
151 インデックスが間違っている場合、あるいは存在しない場合は例外がスローされます。
152 <methodname>count()</methodname> を使って結果の行数を確認してから移動するようにしましょう。
155 <programlisting language="php"><![CDATA[
158 // テーブルのすべてのレコードを取得します
159 $rowset = $bugs->fetchAll();
161 // イテレータを 9 番目の要素に移動します (最初の要素がゼロです)
165 $row9 = $rowset->current();
168 $row9->assigned_to = 'mmouse';
175 <methodname>getRow()</methodname> は、位置がわかっている場合に
176 行セット内の特定の行を取得するためのメソッドです。
177 しかし、この位置はゼロから数え始めることを忘れないようにしましょう。
178 <methodname>getRow()</methodname> の最初のパラメータは、位置を表す整数値です。
179 2 番目のパラメータはオプションで、boolean 値を指定します。
180 これは、Rowset イテレータも同時にその場所に移動させるのかどうかを表します
181 (デフォルトは <constant>FALSE</constant> です)。このメソッドはデフォルトでは
182 <classname>Zend_Db_Table_Row</classname> オブジェクトを返します。
183 指定した位置が存在しない場合は例外をスローします。
187 <programlisting language="php"><![CDATA[
190 // テーブルのすべてのレコードを取得します
191 $rowset = $bugs->fetchAll();
197 $row9->assigned_to = 'mmouse';
202 個々の行オブジェクトにアクセスすると、後は
203 <link linkend="zend.db.table.row">Zend_Db_Table_Row</link>
204 で説明しているメソッド群を用いて行を操作できます。
209 <sect2 id="zend.db.table.rowset.to-array">
211 <title>行セットの配列としての取得</title>
214 行セット内のすべてのデータに対して配列としてアクセスするには、
215 行セットオブジェクトの <methodname>toArray()</methodname> メソッドを使用します。
216 これは、各行単位でひとつの要素となる配列を返します。
217 各エントリは連想配列となり、カラム名とその値が関連付けられています。
220 <example id="zend.db.table.rowset.to-array.example">
222 <title>toArray() の使用法</title>
224 <programlisting language="php"><![CDATA[
226 $rowset = $bugs->fetchAll();
228 $rowsetArray = $rowset->toArray();
231 foreach ($rowsetArray as $rowArray) {
232 echo "row #$rowCount:\n";
233 foreach ($rowArray as $column => $value) {
234 echo "\t$column => $value\n";
243 <methodname>toArray()</methodname> が返す配列は、更新できません。
244 つまり、配列内の値を変更することは可能ですが、
245 それをデータベースに反映させることはできません。
250 <sect2 id="zend.db.table.rowset.serialize">
252 <title>行セットのシリアライズと復元</title>
255 <classname>Zend_Db_Table_Rowset_Abstract</classname> 型のオブジェクトはシリアライズ可能です。
256 個別の行オブジェクトをシリアライズするのと同じような方式で、
257 行セットをシリアライズして後ほどそれを復元できます。
260 <example id="zend.db.table.rowset.serialize.example.serialize">
262 <title>行セットのシリアライズ</title>
265 <acronym>PHP</acronym> の <methodname>serialize()</methodname> 関数を使用して、
266 行セットオブジェクトのバイトストリームを含む文字列を作成します。
269 <programlisting language="php"><![CDATA[
271 $rowset = $bugs->fetchAll();
274 $serializedRowset = serialize($rowset);
276 // これで、$serializedRowset をファイルなどに書き出すことができます
281 <example id="zend.db.table.rowset.serialize.example.unserialize">
283 <title>シリアライズした行セットの復元</title>
286 <acronym>PHP</acronym> の <methodname>unserialize()</methodname> 関数を使用して、
287 オブジェクトのバイトストリームを含む文字列を復元します。
288 この関数は、もとのオブジェクトを返します。
293 <emphasis>接続が切断された</emphasis> 状態であることに注意しましょう。
294 行セットオブジェクトやその内部の行オブジェクト、そしてそのプロパティを読み込むことはできますが、
295 その値を変更することはできません。また、データベース接続を必要とするようなメソッド
296 (たとえば従属テーブルに対するクエリなど) も実行できません。
299 <programlisting language="php"><![CDATA[
300 $rowsetDisconnected = unserialize($serializedRowset);
302 // これでオブジェクトのプロパティを使用できますが、読み込み専用です
303 $row = $rowsetDisconnected->current();
304 echo $row->bug_description;
310 <title>復元した行セットは、なぜ切断された状態なのですか?</title>
312 シリアライズしたオブジェクトは、可読形式の文字列となります。
313 データベースのアカウントやパスワードといった情報を
314 暗号化せずにプレーンテキストにシリアライズして保存すると、
316 そのようなデータを無防備な状態でテキストファイルに保存したりしたくはないでしょう。
317 またメールなどで攻撃者に覗き見られることも好まないはずです。
319 正しい認証情報を知らない限りデータベースにアクセスすることはできません。
324 切断された行セットの接続を復活させるには、
325 <methodname>setTable()</methodname> メソッドを使用します。このメソッドへの引数としては、
326 <classname>Zend_Db_Table_Abstract</classname> 型のオブジェクトを作成して渡します。
327 テーブルオブジェクトを作成するには、データベースとの接続が必要です。
328 そのテーブルと行セットを関連付けることで、行セットがデータベースにアクセスできるようになります。
329 それ以降は、行オブジェクトの値を変更してデータベースに保存できるようになります。
332 <example id="zend.db.table.rowset.serialize.example.set-table">
334 <title>生きたデータとしての行セットの復活</title>
336 <programlisting language="php"><![CDATA[
337 $rowset = unserialize($serializedRowset);
343 $rowset->setTable($bugs);
345 $row = $rowset->current();
347 // これで、行の内容を変更して保存できます
348 $row->bug_status = 'FIXED';
355 行セットを <methodname>setTable()</methodname> で復活させると、
356 その中に含まれる行オブジェクトもすべて復活した状態になります。
361 <sect2 id="zend.db.table.rowset.extending">
363 <title>行セットクラスの拡張</title>
366 <classname>Zend_Db_Table_Rowset_Abstract</classname> を継承した新たな具象クラスを作成し、
367 それを用いて行セットのインスタンスを作成できます。
368 独自の行クラスを指定するには、テーブルクラスの protected
369 メンバである <varname>$_rowsetClass</varname> を使用するか、
370 テーブルオブジェクトのコンストラクタの引数の配列で指定します。
373 <example id="zend.db.table.rowset.extending.example">
374 <title>独自の行セットクラスの指定</title>
375 <programlisting language="php"><![CDATA[
376 class MyRowset extends Zend_Db_Table_Rowset_Abstract
381 // 独自の行セットを、テーブルクラスの全インスタンスで
382 // デフォルトとして使用するように設定します
383 class Products extends Zend_Db_Table_Abstract
385 protected $_name = 'products';
386 protected $_rowsetClass = 'MyRowset';
389 // あるいは、テーブルクラスの特定のインスタンスでのみ
390 // 独自の行セットクラスを使用するように設定します
391 $bugs = new Bugs(array('rowsetClass' => 'MyRowset'));
396 一般的には、標準の具象クラス <classname>Zend_Db_Rowset</classname>
398 特定のテーブルに固有の処理を行セットに追加したくなることもあります。
399 たとえば、行セット内のすべての行の内容の集計用のメソッドなどです。
402 <example id="zend.db.table.rowset.extending.example-aggregate">
403 <title>行セットクラスに新しいメソッドを追加する例</title>
404 <programlisting language="php"><![CDATA[
405 class MyBugsRowset extends Zend_Db_Table_Rowset_Abstract
408 * 現在の行セットのなかで、'updated_at' カラムの値が
411 public function getLatestUpdatedRow()
415 foreach ($this as $row) {
416 if ($row->updated_at > $max_updated_at) {
424 class Bugs extends Zend_Db_Table_Abstract
426 protected $_name = 'bugs';
427 protected $_rowsetClass = 'MyBugsRowset';