| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- EN-Revision: 24249 -->
- <!-- Reviewed: no -->
- <sect1 id="zend.db.table.row">
- <title>Zend_Db_Table_Row</title>
- <sect2 id="zend.db.table.row.introduction">
- <title>Introducción</title>
- <para>
- <classname>Zend_Db_Table_Row</classname> is a class that contains an
- individual row of a <classname>Zend_Db_Table</classname> object.
- When you run a query against a Table class, the result is returned
- in a set of <classname>Zend_Db_Table_Row</classname> objects. You
- can also use this object to create new rows and add them to the
- database table. </para>
- <para>
- <classname>Zend_Db_Table_Row</classname> is an implementation of the
- <ulink
- url="http://www.martinfowler.com/eaaCatalog/rowDataGateway.html"
- >Row Data Gateway</ulink> pattern. </para>
- </sect2>
- <sect2 id="zend.db.table.row.read">
- <title>Fetching a Row</title>
- <para>
- <classname>Zend_Db_Table_Abstract</classname> provides methods
- <methodname>find()</methodname> and
- <methodname>fetchAll()</methodname> , which each return an
- object of type <classname>Zend_Db_Table_Rowset</classname> , and the
- method <methodname>fetchRow()</methodname> , which returns an object
- of type <classname>Zend_Db_Table_Row</classname> . </para>
- <example id="zend.db.table.row.read.example">
- <title>Example of fetching a row</title>
- <programlisting language="php"><![CDATA[
- $bugs = new Bugs();
- $row = $bugs->fetchRow($bugs->select()->where('bug_id = ?', 1));
- ]]></programlisting>
- </example>
- <para> A <classname>Zend_Db_Table_Rowset</classname> object contains a
- collection of <classname>Zend_Db_Table_Row</classname> objects. See
- <xref linkend="zend.db.table.rowset"/> . </para>
- <example id="zend.db.table.row.read.example-rowset">
- <title>Example of reading a row in a rowset</title>
- <programlisting language="php"><![CDATA[
- $bugs = new Bugs();
- $rowset = $bugs->fetchAll($bugs->select()->where('bug_status = ?', 1));
- $row = $rowset->current();
- ]]></programlisting>
- </example>
- <sect3 id="zend.db.table.row.read.get">
- <title>Reading column values from a row</title>
- <para>
- <classname>Zend_Db_Table_Row_Abstract</classname> provides
- accessor methods so you can reference columns in the row as
- object properties. </para>
- <example id="zend.db.table.row.read.get.example">
- <title>Example of reading a column in a row</title>
- <programlisting language="php"><![CDATA[
- $bugs = new Bugs();
- $row = $bugs->fetchRow($bugs->select()->where('bug_id = ?', 1));
- // Echo the value of the bug_description column
- echo $row->bug_description;
- ]]></programlisting>
- </example>
- <note>
- <para> Earlier versions of
- <classname>Zend_Db_Table_Row</classname> mapped these
- column accessors to the database column names using a string
- transformation called <emphasis>inflection</emphasis> . </para>
- <para> Currently, <classname>Zend_Db_Table_Row</classname> does
- not implement inflection. Accessed property names need to
- match the spelling of the column names as they appear in
- your database. </para>
- </note>
- </sect3>
- <sect3 id="zend.db.table.row.read.to-array">
- <title>Retrieving Row Data as an Array</title>
- <para> You can access the row's data as an array using the
- <methodname>toArray()</methodname> method of the Row object.
- This returns an associative array of the column names to the
- column values. </para>
- <example id="zend.db.table.row.read.to-array.example">
- <title>Example of using the toArray() method</title>
- <programlisting language="php"><![CDATA[
- $bugs = new Bugs();
- $row = $bugs->fetchRow($bugs->select()->where('bug_id = ?', 1));
- // Get the column/value associative array from the Row object
- $rowArray = $row->toArray();
- // Now use it as a normal array
- foreach ($rowArray as $column => $value) {
- echo "Column: $column\n";
- echo "Value: $value\n";
- }
- ]]></programlisting>
- </example>
- <para> The array returned from <methodname>toArray()</methodname> is
- not updateable. You can modify values in the array as you can
- with any array, but you cannot save changes to this array to the
- database directly. </para>
- </sect3>
- <sect3 id="zend.db.table.row.read.relationships">
- <title>Fetching data from related tables</title>
- <para> The <classname>Zend_Db_Table_Row_Abstract</classname> class
- provides methods for fetching rows and rowsets from related
- tables. See <xref linkend="zend.db.table.relationships"/> for
- more information on table relationships. </para>
- </sect3>
- </sect2>
- <sect2 id="zend.db.table.row.write">
- <title>Writing rows to the database</title>
- <sect3 id="zend.db.table.row.write.set">
- <title>Changing column values in a row</title>
- <para>You can set individual column values using column accessors,
- similar to how the columns are read as object properties in the
- example above.</para>
- <para> Using a column accessor to set a value changes the column
- value of the row object in your application, but it does not
- commit the change to the database yet. You can do that with the
- <methodname>save()</methodname> method. </para>
- <example id="zend.db.table.row.write.set.example">
- <title>Example of changing a column in a row</title>
- <programlisting language="php"><![CDATA[
- $bugs = new Bugs();
- $row = $bugs->fetchRow($bugs->select()->where('bug_id = ?', 1));
- // Change the value of one or more columns
- $row->bug_status = 'FIXED';
- // UPDATE the row in the database with new values
- $row->save();
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.table.row.write.insert">
- <title>Inserting a new row</title>
- <para> You can create a new row for a given table with the
- <methodname>createRow()</methodname> method of the table
- class. You can access fields of this row with the
- object-oriented interface, but the row is not stored in the
- database until you call the <methodname>save()</methodname>
- method. </para>
- <example id="zend.db.table.row.write.insert.example">
- <title>Example of creating a new row for a table</title>
- <programlisting language="php"><![CDATA[
- $bugs = new Bugs();
- $newRow = $bugs->createRow();
- // Set column values as appropriate for your application
- $newRow->bug_description = '...description...';
- $newRow->bug_status = 'NEW';
- // INSERT the new row to the database
- $newRow->save();
- ]]></programlisting>
- </example>
- <para>The optional argument to the createRow() method is an
- associative array, with which you can populate fields of the new
- row.</para>
- <example id="zend.db.table.row.write.insert.example2">
- <title>Example of populating a new row for a table</title>
- <programlisting language="php"><![CDATA[
- $data = array(
- 'bug_description' => '...description...',
- 'bug_status' => 'NEW'
- );
- $bugs = new Bugs();
- $newRow = $bugs->createRow($data);
- // INSERT the new row to the database
- $newRow->save();
- ]]></programlisting>
- </example>
- <note>
- <para> The <methodname>createRow()</methodname> method was
- called <methodname>fetchNew()</methodname> in earlier
- releases of <classname>Zend_Db_Table</classname> . You are
- encouraged to use the new method name, even though the old
- name continues to work for the sake of backward
- compatibility. </para>
- </note>
- </sect3>
- <sect3 id="zend.db.table.row.write.set-from-array">
- <title>Changing values in multiple columns</title>
- <para>
- <classname>Zend_Db_Table_Row_Abstract</classname> provides the
- <methodname>setFromArray()</methodname> method to enable you
- to set several columns in a single row at once, specified in an
- associative array that maps the column names to values. You may
- find this method convenient for setting values both for new rows
- and for rows you need to update. </para>
- <example id="zend.db.table.row.write.set-from-array.example">
- <title>Example of using setFromArray() to set values in a new
- Row</title>
- <programlisting language="php"><![CDATA[
- $bugs = new Bugs();
- $newRow = $bugs->createRow();
- // Data are arranged in an associative array
- $data = array(
- 'bug_description' => '...description...',
- 'bug_status' => 'NEW'
- );
- // Set all the column values at once
- $newRow->setFromArray($data);
- // INSERT the new row to the database
- $newRow->save();
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.table.row.write.delete">
- <title>Deleting a row</title>
- <para> You can call the <methodname>delete()</methodname> method on
- a Row object. This deletes rows in the database matching the
- primary key in the Row object. </para>
- <example id="zend.db.table.row.write.delete.example">
- <title>Example of deleting a row</title>
- <programlisting language="php"><![CDATA[
- $bugs = new Bugs();
- $row = $bugs->fetchRow('bug_id = 1');
- // DELETE this row
- $row->delete();
- ]]></programlisting>
- </example>
- <para> You do not have to call <methodname>save()</methodname> to
- apply the delete; it is executed against the database
- immediately. </para>
- </sect3>
- </sect2>
- <sect2 id="zend.db.table.row.serialize">
- <title>Serializing and unserializing rows</title>
- <para> It is often convenient to save the contents of a database row to
- be used later. <emphasis>Serialization</emphasis> is the name for
- the operation that converts an object into a form that is easy to
- save in offline storage (for example, a file). Objects of type
- <classname>Zend_Db_Table_Row_Abstract</classname> are
- serializable. </para>
- <sect3 id="zend.db.table.row.serialize.serializing">
- <title>Serializing a Row</title>
- <para> Simply use <acronym>PHP</acronym> 's
- <methodname>serialize()</methodname> function to create a
- string containing a byte-stream representation of the Row object
- argument. </para>
- <example id="zend.db.table.row.serialize.serializing.example">
- <title>Example of serializing a row</title>
- <programlisting language="php"><![CDATA[
- $bugs = new Bugs();
- $row = $bugs->fetchRow('bug_id = 1');
- // Convert object to serialized form
- $serializedRow = serialize($row);
- // Now you can write $serializedRow to a file, etc.
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.table.row.serialize.unserializing">
- <title>Unserializing Row Data</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 Row object returned is in a
- <emphasis>disconnected</emphasis> state. You can read the
- Row object and its properties, but you cannot change values in
- the Row or execute other methods that require a database
- connection (for example, queries against related tables). </para>
- <example id="zend.db.table.row.serialize.unserializing.example">
- <title>Example of unserializing a serialized row</title>
- <programlisting language="php"><![CDATA[
- $rowClone = unserialize($serializedRow);
- // Now you can use object properties, but read-only
- echo $rowClone->bug_description;
- ]]></programlisting>
- </example>
- <note>
- <title>Why do Rows 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>
- </sect3>
- <sect3 id="zend.db.table.row.serialize.set-table">
- <title>Reactivating a Row as Live Data</title>
- <para> You can reactivate a disconnected Row, 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 Row, the
- Row gains access to the database. Subsequently, you can change
- values in the Row object and save the changes to the database. </para>
- <example id="zend.db.table.row.serialize.set-table.example">
- <title>Example of reactivating a row</title>
- <programlisting language="php"><![CDATA[
- $rowClone = unserialize($serializedRow);
- $bugs = new Bugs();
- // Reconnect the row to a table, and
- // thus to a live database connection
- $rowClone->setTable($bugs);
- // Now you can make changes to the row and save them
- $rowClone->bug_status = 'FIXED';
- $rowClone->save();
- ]]></programlisting>
- </example>
- </sect3>
- </sect2>
- <sect2 id="zend.db.table.row.extending">
- <title>Extending the Row class</title>
- <para>
- <classname>Zend_Db_Table_Row</classname> is the default concrete
- class that extends <classname>Zend_Db_Table_Row_Abstract</classname>
- . You can define your own concrete class for instances of Row by
- extending <classname>Zend_Db_Table_Row_Abstract</classname> . To use
- your new Row class to store results of Table queries, specify the
- custom Row class by name either in the <varname>$_rowClass</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.row.extending.example">
- <title>Specifying a custom Row class</title>
- <programlisting language="php"><![CDATA[
- class MyRow extends Zend_Db_Table_Row_Abstract
- {
- // ...customizations
- }
- // Specify a custom Row to be used by default
- // in all instances of a Table class.
- class Products extends Zend_Db_Table_Abstract
- {
- protected $_name = 'products';
- protected $_rowClass = 'MyRow';
- }
- // Or specify a custom Row to be used in one
- // instance of a Table class.
- $bugs = new Bugs(array('rowClass' => 'MyRow'));
- ]]></programlisting>
- </example>
- <sect3 id="zend.db.table.row.extending.overriding">
- <title>Row initialization</title>
- <para> If application-specific logic needs to be initialized when a
- row is constructed, you can select to move your tasks to the
- <methodname>init()</methodname> method, which is called
- after all row metadata has been processed. This is recommended
- over the <methodname>__construct</methodname> method if you do
- not need to alter the metadata in any programmatic way. <example
- id="zend.db.table.row.init.usage.example">
- <title>Example usage of init() method</title>
- <programlisting language="php"><![CDATA[
- class MyApplicationRow extends Zend_Db_Table_Row_Abstract
- {
- protected $_role;
- public function init()
- {
- $this->_role = new MyRoleClass();
- }
- }
- ]]></programlisting>
- </example>
- </para>
- </sect3>
- <sect3 id="zend.db.table.row.extending.insert-update">
- <title>Defining Custom Logic for Insert, Update, and Delete in
- Zend_Db_Table_Row</title>
- <para> The Row class calls protected methods
- <methodname>_insert()</methodname> ,
- <methodname>_update()</methodname> , and
- <methodname>_delete()</methodname> before performing the
- corresponding operations <methodname>INSERT</methodname> ,
- <methodname>UPDATE</methodname> , and
- <methodname>DELETE</methodname> . You can add logic to these
- methods in your custom Row subclass. </para>
- <para> If you need to do custom logic in a specific table, and the
- custom logic must occur for every operation on that table, it
- may make more sense to implement your custom code in the
- <methodname>insert()</methodname> ,
- <methodname>update()</methodname> and
- <methodname>delete()</methodname> methods of your Table
- class. However, sometimes it may be necessary to do custom logic
- in the Row class. </para>
- <para>Below are some example cases where it might make sense to
- implement custom logic in a Row class instead of in the Table
- class:</para>
- <example id="zend.db.table.row.extending.overriding-example1">
- <title>Example of custom logic in a Row class</title>
- <para>The custom logic may not apply in all cases of operations
- on the respective Table. You can provide custom logic on
- demand by implementing it in a Row class and creating an
- instance of the Table class with that custom Row class
- specified. Otherwise, the Table uses the default Row
- class.</para>
- <para> You need data operations on this table to record the
- operation to a <classname>Zend_Log</classname> object, but
- only if the application configuration has enabled this
- behavior. </para>
- <programlisting language="php"><![CDATA[
- class MyLoggingRow extends Zend_Db_Table_Row_Abstract
- {
- protected function _insert()
- {
- $log = Zend_Registry::get('database_log');
- $log->info(Zend_Debug::dump($this->_data,
- "INSERT: $this->_tableClass",
- false)
- );
- }
- }
- // $loggingEnabled is an example property that depends
- // on your application configuration
- if ($loggingEnabled) {
- $bugs = new Bugs(array('rowClass' => 'MyLoggingRow'));
- } else {
- $bugs = new Bugs();
- }
- ]]></programlisting>
- </example>
- <example id="zend.db.table.row.extending.overriding-example2">
- <title>Example of a Row class that logs insert data for multiple
- tables</title>
- <para>The custom logic may be common to multiple tables. Instead
- of implementing the same custom logic in every one of your
- Table classes, you can implement the code for such actions
- in the definition of a Row class, and use this Row in each
- of your Table classes.</para>
- <para>In this example, the logging code is identical in all
- table classes.</para>
- <programlisting language="php"><![CDATA[
- class MyLoggingRow extends Zend_Db_Table_Row_Abstract
- {
- protected function _insert()
- {
- $log = Zend_Registry::get('database_log');
- $log->info(Zend_Debug::dump($this->_data,
- "INSERT: $this->_tableClass",
- false)
- );
- }
- }
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs';
- protected $_rowClass = 'MyLoggingRow';
- }
- class Products extends Zend_Db_Table_Abstract
- {
- protected $_name = 'products';
- protected $_rowClass = 'MyLoggingRow';
- }
- ]]></programlisting>
- </example>
- </sect3>
- <sect3 id="zend.db.table.row.extending.inflection">
- <title>Define Inflection in Zend_Db_Table_Row</title>
- <para> Some people prefer that the table class name match a table
- name in the <acronym>RDBMS</acronym> by using a string
- transformation called <emphasis>inflection</emphasis> . </para>
- <para>
- <classname>Zend_Db</classname> classes do not implement
- inflection by default. See <xref
- linkend="zend.db.table.extending.inflection"/> for an
- explanation of this policy. </para>
- <para> If you prefer to use inflection, then you must implement the
- transformation yourself, by overriding the
- <methodname>_transformColumn()</methodname> method in a
- custom Row class, and using that custom Row class when you
- perform queries against your Table class. </para>
- <example id="zend.db.table.row.extending.inflection.example">
- <title>Example of defining an inflection transformation</title>
- <para> This allows you to use an inflected version of the column
- name in the accessors. The Row class uses the
- <methodname>_transformColumn()</methodname> method to
- change the name you use to the native column name in the
- database table. </para>
- <programlisting language="php"><![CDATA[
- class MyInflectedRow extends Zend_Db_Table_Row_Abstract
- {
- protected function _transformColumn($columnName)
- {
- $nativeColumnName = myCustomInflector($columnName);
- return $nativeColumnName;
- }
- }
- class Bugs extends Zend_Db_Table_Abstract
- {
- protected $_name = 'bugs';
- protected $_rowClass = 'MyInflectedRow';
- }
- $bugs = new Bugs();
- $row = $bugs->fetchNew();
- // Use camelcase column names, and rely on the
- // transformation function to change it into the
- // native representation.
- $row->bugDescription = 'New description';
- ]]></programlisting>
- </example>
- <para>You are responsible for writing the functions to perform
- inflection transformation. Zend Framework does not provide such
- a function.</para>
- </sect3>
- </sect2>
- </sect1>
|