| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- 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 <code>find()</code> or
- <code>fetchAll()</code> 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 <code>find()</code> and
- <code>fetchAll()</code>, 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
- <code>Countable</code> interface, you can use <code>count()</code> 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 <code>current()</code>
- 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, <code>current()</code> 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 <code>SeekableIterator</code> interface, which means you can loop
- through them using the <code>foreach</code> 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>
- <code>SeekableIterator</code> allows you to seek to a position that you would like
- the iterator to jump to. Simply use the <code>seek()</code> 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 <code>count()</code> 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>
- <code>getRow()</code> 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 <code>getRow()</code> 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 false). 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 <code>toArray()</code>
- 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 <code>toArray()</code> 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 <code>serialize()</code> 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 <code>unserialize()</code> 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 <code>setTable()</code> 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 <code>setTable()</code> 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>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|