| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- EN-Revision: 24249 -->
- <!-- Reviewed: no -->
- <sect1 id="zend.db.table.rowset">
- <title>Zend_Db_Table_Rowset</title>
- <sect2 id="zend.db.table.rowset.introduction">
- <title>Introduction</title>
- <para> When you run a query against a Table class using the
- <methodname>find()</methodname> or
- <methodname>fetchAll()</methodname> methods, the result is
- returned in an object of type
- <classname>Zend_Db_Table_Rowset_Abstract</classname> . A Rowset
- contains a collection of objects descending from
- <classname>Zend_Db_Table_Row_Abstract</classname> . You can
- iterate through the Rowset and access individual Row objects,
- reading or modifying data in the Rows. </para>
- </sect2>
- <sect2 id="zend.db.table.rowset.fetch">
- <title>Fetching a Rowset</title>
- <para>
- <classname>Zend_Db_Table_Abstract</classname> provides methods
- <methodname>find()</methodname> and
- <methodname>fetchAll()</methodname> , each of which returns an
- object of type <classname>Zend_Db_Table_Rowset_Abstract</classname>
- . </para>
- <example id="zend.db.table.rowset.fetch.example">
- <title>Example of fetching a rowset</title>
- <programlisting language="php"><![CDATA[
- $bugs = new Bugs();
- $rowset = $bugs->fetchAll("bug_status = 'NEW'");
- ]]></programlisting>
- </example>
- </sect2>
- <sect2 id="zend.db.table.rowset.rows">
- <title>Retrieving Rows from a Rowset</title>
- <para> The Rowset itself is usually less interesting than the Rows that
- it contains. This section illustrates how to get the Rows that
- comprise the Rowset. </para>
- <para> A legitimate query returns zero rows when no rows in the database
- match the query conditions. Therefore, a Rowset object might contain
- zero Row objects. Since
- <classname>Zend_Db_Table_Rowset_Abstract</classname> implements
- the <methodname>Countable</methodname> interface, you can use
- <methodname>count()</methodname> to determine the number of Rows
- in the Rowset. </para>
- <example id="zend.db.table.rowset.rows.counting.example">
- <title>Counting the Rows in a Rowset</title>
- <programlisting language="php"><![CDATA[
- $rowset = $bugs->fetchAll("bug_status = 'FIXED'");
- $rowCount = count($rowset);
- if ($rowCount > 0) {
- echo "found $rowCount rows";
- } else {
- echo 'no rows matched the query';
- }
- ]]></programlisting>
- </example>
- <example id="zend.db.table.rowset.rows.current.example">
- <title>Reading a Single Row from a Rowset</title>
- <para> The simplest way to access a Row from a Rowset is to use the
- <methodname>current()</methodname> method. This is
- particularly appropriate when the Rowset contains exactly one
- Row. </para>
- <programlisting language="php"><![CDATA[
- $bugs = new Bugs();
- $rowset = $bugs->fetchAll("bug_id = 1");
- $row = $rowset->current();
- ]]></programlisting>
- </example>
- <para> If the Rowset contains zero rows,
- <methodname>current()</methodname> returns PHP's
- <constant>NULL</constant> value. </para>
- <example id="zend.db.table.rowset.rows.iterate.example">
- <title>Iterating through a Rowset</title>
- <para> Objects descending from
- <classname>Zend_Db_Table_Rowset_Abstract</classname>
- implement the <methodname>SeekableIterator</methodname>
- interface, which means you can loop through them using the
- <methodname>foreach</methodname> construct. Each value you
- retrieve this way is a
- <classname>Zend_Db_Table_Row_Abstract</classname> object
- that corresponds to one record from the table. </para>
- <programlisting language="php"><![CDATA[
- $bugs = new Bugs();
- // fetch all records from the table
- $rowset = $bugs->fetchAll();
- foreach ($rowset as $row) {
- // output 'Zend_Db_Table_Row' or similar
- echo get_class($row) . "\n";
- // read a column in the row
- $status = $row->bug_status;
- // modify a column in the current row
- $row->assigned_to = 'mmouse';
- // write the change to the database
- $row->save();
- }
- ]]></programlisting>
- </example>
- <example id="zend.db.table.rowset.rows.seek.example">
- <title>Seeking to a known position into a Rowset</title>
- <para>
- <methodname>SeekableIterator</methodname> allows you to seek to
- a position that you would like the iterator to jump to. Simply
- use the <methodname>seek()</methodname> method for that. Pass it
- an integer representing the number of the Row you would like
- your Rowset to point to next, don't forget that it starts with
- index 0. If the index is wrong, ie doesn't exist, an exception
- will be thrown. You should use <methodname>count()</methodname>
- to check the number of results before seeking to a position. </para>
- <programlisting language="php"><![CDATA[
- $bugs = new Bugs();
- // fetch all records from the table
- $rowset = $bugs->fetchAll();
- // takes the iterator to the 9th element (zero is one element) :
- $rowset->seek(8);
- // retrieve it
- $row9 = $rowset->current();
- // and use it
- $row9->assigned_to = 'mmouse';
- $row9->save();
- ]]></programlisting>
- </example>
- <para>
- <methodname>getRow()</methodname> allows you to get a specific row
- in the Rowset, knowing its position; don't forget however that
- positions start with index zero. The first parameter for
- <methodname>getRow()</methodname> is an integer for the position
- asked. The second optional parameter is a boolean; it tells the
- Rowset iterator if it must seek to that position in the same time,
- or not (default is <constant>FALSE</constant>). This method returns a
- <classname>Zend_Db_Table_Row</classname> object by default. If
- the position requested does not exist, an exception will be thrown.
- Here is an example : </para>
- <programlisting language="php"><![CDATA[
- $bugs = new Bugs();
- // fetch all records from the table
- $rowset = $bugs->fetchAll();
- // retrieve the 9th element immediately:
- $row9->getRow(8);
- // and use it:
- $row9->assigned_to = 'mmouse';
- $row9->save();
- ]]></programlisting>
- <para> After you have access to an individual Row object, you can
- manipulate the Row using methods described in <xref
- linkend="zend.db.table.row"/> . </para>
- </sect2>
- <sect2 id="zend.db.table.rowset.to-array">
- <title>Retrieving a Rowset as an Array</title>
- <para> You can access all the data in the Rowset as an array using the
- <methodname>toArray()</methodname> method of the Rowset object.
- This returns an array containing one entry per Row. Each entry is an
- associative array having keys that correspond to column names and
- elements that correspond to the respective column values. </para>
- <example id="zend.db.table.rowset.to-array.example">
- <title>Using toArray()</title>
- <programlisting language="php"><![CDATA[
- $bugs = new Bugs();
- $rowset = $bugs->fetchAll();
- $rowsetArray = $rowset->toArray();
- $rowCount = 1;
- foreach ($rowsetArray as $rowArray) {
- echo "row #$rowCount:\n";
- foreach ($rowArray as $column => $value) {
- echo "\t$column => $value\n";
- }
- ++$rowCount;
- echo "\n";
- }
- ]]></programlisting>
- </example>
- <para> The array returned from <methodname>toArray()</methodname> is not
- updateable. That is, you can modify values in the array as you can
- with any array, but changes to the array data are not propagated to
- the database. </para>
- </sect2>
- <sect2 id="zend.db.table.rowset.serialize">
- <title>Serializing and Unserializing a Rowset</title>
- <para> Objects of type
- <classname>Zend_Db_Table_Rowset_Abstract</classname> are
- serializable. In a similar fashion to serializing an individual Row
- object, you can serialize a Rowset and unserialize it later. </para>
- <example id="zend.db.table.rowset.serialize.example.serialize">
- <title>Serializing a Rowset</title>
- <para> Simply use PHP's <methodname>serialize()</methodname>
- function to create a string containing a byte-stream
- representation of the Rowset object argument. </para>
- <programlisting language="php"><![CDATA[
- $bugs = new Bugs();
- $rowset = $bugs->fetchAll();
- // Convert object to serialized form
- $serializedRowset = serialize($rowset);
- // Now you can write $serializedRowset to a file, etc.
- ]]></programlisting>
- </example>
- <example id="zend.db.table.rowset.serialize.example.unserialize">
- <title>Unserializing a Serialized Rowset</title>
- <para> Use PHP's <methodname>unserialize()</methodname> function to
- restore a string containing a byte-stream representation of an
- object. The function returns the original object. </para>
- <para> Note that the Rowset object returned is in a
- <emphasis>disconnected</emphasis> state. You can iterate
- through the Rowset and read the Row objects and their
- properties, but you cannot change values in the Rows or execute
- other methods that require a database connection (for example,
- queries against related tables). </para>
- <programlisting language="php"><![CDATA[
- $rowsetDisconnected = unserialize($serializedRowset);
- // Now you can use object methods and properties, but read-only
- $row = $rowsetDisconnected->current();
- echo $row->bug_description;
- ]]></programlisting>
- </example>
- <note>
- <title>Why do Rowsets unserialize in a disconnected state?</title>
- <para> A serialized object is a string that is readable to anyone
- who possesses it. It could be a security risk to store
- parameters such as database account and password in plain,
- unencrypted text in the serialized string. You would not want to
- store such data to a text file that is not protected, or send it
- in an email or other medium that is easily read by potential
- attackers. The reader of the serialized object should not be
- able to use it to gain access to your database without knowing
- valid credentials. </para>
- </note>
- <para> You can reactivate a disconnected Rowset using the
- <methodname>setTable()</methodname> method. The argument to this
- method is a valid object of type
- <classname>Zend_Db_Table_Abstract</classname> , which you
- create. Creating a Table object requires a live connection to the
- database, so by reassociating the Table with the Rowset, the Rowset
- gains access to the database. Subsequently, you can change values in
- the Row objects contained in the Rowset and save the changes to the
- database. </para>
- <example id="zend.db.table.rowset.serialize.example.set-table">
- <title>Reactivating a Rowset as Live Data</title>
- <programlisting language="php"><![CDATA[
- $rowset = unserialize($serializedRowset);
- $bugs = new Bugs();
- // Reconnect the rowset to a table, and
- // thus to a live database connection
- $rowset->setTable($bugs);
- $row = $rowset->current();
- // Now you can make changes to the row and save them
- $row->bug_status = 'FIXED';
- $row->save();
- ]]></programlisting>
- </example>
- <para> Reactivating a Rowset with <methodname>setTable()</methodname>
- also reactivates all the Row objects contained in that Rowset. </para>
- </sect2>
- <sect2 id="zend.db.table.rowset.extending">
- <title>Extending the Rowset class</title>
- <para> You can use an alternative concrete class for instances of
- Rowsets by extending
- <classname>Zend_Db_Table_Rowset_Abstract</classname> . Specify
- the custom Rowset class by name either in the
- <varname>$_rowsetClass</varname> protected member of a Table
- class, or in the array argument of the constructor of a Table
- object. </para>
- <example id="zend.db.table.rowset.extending.example">
- <title>Specifying a custom Rowset class</title>
- <programlisting language="php"><![CDATA[
- class MyRowset extends Zend_Db_Table_Rowset_Abstract
- {
- // ...customizations
- }
- // Specify a custom Rowset to be used by default
- // in all instances of a Table class.
- class Products extends Zend_Db_Table_Abstract
- {
- protected $_name = 'products';
- protected $_rowsetClass = 'MyRowset';
- }
- // Or specify a custom Rowset to be used in one
- // instance of a Table class.
- $bugs = new Bugs(array('rowsetClass' => 'MyRowset'));
- ]]></programlisting>
- </example>
- <para> Typically, the standard <classname>Zend_Db_Rowset</classname>
- concrete class is sufficient for most usage. However, you might find
- it useful to add new logic to a Rowset, specific to a given Table.
- For example, a new method could calculate an aggregate over all the
- Rows in the Rowset. </para>
- <example id="zend.db.table.rowset.extending.example-aggregate">
- <title>Example of Rowset class with a new method</title>
- <programlisting language="php"><![CDATA[
- class MyBugsRowset extends Zend_Db_Table_Rowset_Abstract
- {
- /**
- * Find the Row in the current Rowset with the
- * greatest value in its 'updated_at' column.
- */
- public function getLatestUpdatedRow()
- {
- $max_updated_at = 0;
- $latestRow = null;
- foreach ($this as $row) {
- if ($row->updated_at > $max_updated_at) {
- $latestRow = $row;
- }
- }
- return $latestRow;
- }
- }
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs';
- protected $_rowsetClass = 'MyBugsRowset';
- }
- ]]></programlisting>
- </example>
- </sect2>
- </sect1>
|