| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404 |
- <?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 <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
- <classname>Countable</classname> 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
- <acronym>PHP</acronym>'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 <classname>SeekableIterator</classname> 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>
- <classname>SeekableIterator</classname> 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 = $rowset->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 <link linkend="zend.db.table.row">Zend_Db_Table_Row</link>.
- </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 <acronym>PHP</acronym>'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 <acronym>PHP</acronym>'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>
- <!--
- vim:se ts=4 sw=4 et:
- -->
|