| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870 |
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- EN-Revision: 19484 -->
- <!-- 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>
|