[ZF-10089] Zend_Log
[zend.git] / documentation / manual / es / module_specs / Zend_Db_Table_Row.xml
blob8c68eca96eb33017a21d2dee8dd7defa96f49150
1 <?xml version="1.0" encoding="UTF-8"?>
2     <!-- EN-Revision: 20766 -->
3     <!-- Reviewed: no -->
4 <sect1 id="zend.db.table.row">
6     <title>Zend_Db_Table_Row</title>
8     <sect2 id="zend.db.table.row.introduction">
10         <title>Introducción</title>
12         <para>
13             <classname>Zend_Db_Table_Row</classname> is a class that contains an
14             individual row of a <classname>Zend_Db_Table</classname> object.
15             When you run a query against a Table class, the result is returned
16             in a set of <classname>Zend_Db_Table_Row</classname> objects. You
17             can also use this object to create new rows and add them to the
18             database table. </para>
20         <para>
21             <classname>Zend_Db_Table_Row</classname> is an implementation of the
22                 <ulink
23                 url="http://www.martinfowler.com/eaaCatalog/rowDataGateway.html"
24                 >Row Data Gateway</ulink> pattern. </para>
26     </sect2>
28     <sect2 id="zend.db.table.row.read">
30         <title>Fetching a Row</title>
32         <para>
33             <classname>Zend_Db_Table_Abstract</classname> provides methods
34                 <methodname>find()</methodname> and
35                 <methodname>fetchAll()</methodname> , which each return an
36             object of type <classname>Zend_Db_Table_Rowset</classname> , and the
37             method <methodname>fetchRow()</methodname> , which returns an object
38             of type <classname>Zend_Db_Table_Row</classname> . </para>
40         <example id="zend.db.table.row.read.example">
42             <title>Example of fetching a row</title>
44             <programlisting language="php"><![CDATA[
45 $bugs = new Bugs();
46 $row = $bugs->fetchRow($bugs->select()->where('bug_id = ?', 1));
47 ]]></programlisting>
49         </example>
51         <para> A <classname>Zend_Db_Table_Rowset</classname> object contains a
52             collection of <classname>Zend_Db_Table_Row</classname> objects. See
53                 <xref linkend="zend.db.table.rowset"/> . </para>
55         <example id="zend.db.table.row.read.example-rowset">
57             <title>Example of reading a row in a rowset</title>
59             <programlisting language="php"><![CDATA[
60 $bugs = new Bugs();
61 $rowset = $bugs->fetchAll($bugs->select()->where('bug_status = ?', 1));
62 $row = $rowset->current();
63 ]]></programlisting>
65         </example>
67         <sect3 id="zend.db.table.row.read.get">
69             <title>Reading column values from a row</title>
71             <para>
72                 <classname>Zend_Db_Table_Row_Abstract</classname> provides
73                 accessor methods so you can reference columns in the row as
74                 object properties. </para>
76             <example id="zend.db.table.row.read.get.example">
78                 <title>Example of reading a column in a row</title>
80                 <programlisting language="php"><![CDATA[
81 $bugs = new Bugs();
82 $row = $bugs->fetchRow($bugs->select()->where('bug_id = ?', 1));
84 // Echo the value of the bug_description column
85 echo $row->bug_description;
86 ]]></programlisting>
88             </example>
90             <note>
92                 <para> Earlier versions of
93                         <classname>Zend_Db_Table_Row</classname> mapped these
94                     column accessors to the database column names using a string
95                     transformation called <emphasis>inflection</emphasis> . </para>
97                 <para> Currently, <classname>Zend_Db_Table_Row</classname> does
98                     not implement inflection. Accessed property names need to
99                     match the spelling of the column names as they appear in
100                     your database. </para>
102             </note>
104         </sect3>
106         <sect3 id="zend.db.table.row.read.to-array">
108             <title>Retrieving Row Data as an Array</title>
110             <para> You can access the row's data as an array using the
111                     <methodname>toArray()</methodname> method of the Row object.
112                 This returns an associative array of the column names to the
113                 column values. </para>
115             <example id="zend.db.table.row.read.to-array.example">
117                 <title>Example of using the toArray() method</title>
119                 <programlisting language="php"><![CDATA[
120 $bugs = new Bugs();
121 $row = $bugs->fetchRow($bugs->select()->where('bug_id = ?', 1));
123 // Get the column/value associative array from the Row object
124 $rowArray = $row->toArray();
126 // Now use it as a normal array
127 foreach ($rowArray as $column => $value) {
128     echo "Column: $column\n";
129     echo "Value:  $value\n";
131 ]]></programlisting>
133             </example>
135             <para> The array returned from <methodname>toArray()</methodname> is
136                 not updateable. You can modify values in the array as you can
137                 with any array, but you cannot save changes to this array to the
138                 database directly. </para>
140         </sect3>
142         <sect3 id="zend.db.table.row.read.relationships">
144             <title>Fetching data from related tables</title>
146             <para> The <classname>Zend_Db_Table_Row_Abstract</classname> class
147                 provides methods for fetching rows and rowsets from related
148                 tables. See <xref linkend="zend.db.table.relationships"/> for
149                 more information on table relationships. </para>
151         </sect3>
153     </sect2>
155     <sect2 id="zend.db.table.row.write">
157         <title>Writing rows to the database</title>
159         <sect3 id="zend.db.table.row.write.set">
161             <title>Changing column values in a row</title>
163             <para>You can set individual column values using column accessors,
164                 similar to how the columns are read as object properties in the
165                 example above.</para>
167             <para> Using a column accessor to set a value changes the column
168                 value of the row object in your application, but it does not
169                 commit the change to the database yet. You can do that with the
170                     <methodname>save()</methodname> method. </para>
172             <example id="zend.db.table.row.write.set.example">
174                 <title>Example of changing a column in a row</title>
176                 <programlisting language="php"><![CDATA[
177 $bugs = new Bugs();
178 $row = $bugs->fetchRow($bugs->select()->where('bug_id = ?', 1));
180 // Change the value of one or more columns
181 $row->bug_status = 'FIXED';
183 // UPDATE the row in the database with new values
184 $row->save();
185 ]]></programlisting>
187             </example>
189         </sect3>
191         <sect3 id="zend.db.table.row.write.insert">
193             <title>Inserting a new row</title>
195             <para> You can create a new row for a given table with the
196                     <methodname>createRow()</methodname> method of the table
197                 class. You can access fields of this row with the
198                 object-oriented interface, but the row is not stored in the
199                 database until you call the <methodname>save()</methodname>
200                 method. </para>
202             <example id="zend.db.table.row.write.insert.example">
204                 <title>Example of creating a new row for a table</title>
206                 <programlisting language="php"><![CDATA[
207 $bugs = new Bugs();
208 $newRow = $bugs->createRow();
210 // Set column values as appropriate for your application
211 $newRow->bug_description = '...description...';
212 $newRow->bug_status = 'NEW';
214 // INSERT the new row to the database
215 $newRow->save();
216 ]]></programlisting>
218             </example>
220             <para>The optional argument to the createRow() method is an
221                 associative array, with which you can populate fields of the new
222                 row.</para>
224             <example id="zend.db.table.row.write.insert.example2">
226                 <title>Example of populating a new row for a table</title>
228                 <programlisting language="php"><![CDATA[
229 $data = array(
230     'bug_description' => '...description...',
231     'bug_status'      => 'NEW'
234 $bugs = new Bugs();
235 $newRow = $bugs->createRow($data);
237 // INSERT the new row to the database
238 $newRow->save();
239 ]]></programlisting>
241             </example>
243             <note>
245                 <para> The <methodname>createRow()</methodname> method was
246                     called <methodname>fetchNew()</methodname> in earlier
247                     releases of <classname>Zend_Db_Table</classname> . You are
248                     encouraged to use the new method name, even though the old
249                     name continues to work for the sake of backward
250                     compatibility. </para>
252             </note>
254         </sect3>
256         <sect3 id="zend.db.table.row.write.set-from-array">
258             <title>Changing values in multiple columns</title>
260             <para>
261                 <classname>Zend_Db_Table_Row_Abstract</classname> provides the
262                     <methodname>setFromArray()</methodname> method to enable you
263                 to set several columns in a single row at once, specified in an
264                 associative array that maps the column names to values. You may
265                 find this method convenient for setting values both for new rows
266                 and for rows you need to update. </para>
268             <example id="zend.db.table.row.write.set-from-array.example">
270                 <title>Example of using setFromArray() to set values in a new
271                     Row</title>
273                 <programlisting language="php"><![CDATA[
274 $bugs = new Bugs();
275 $newRow = $bugs->createRow();
277 // Data are arranged in an associative array
278 $data = array(
279     'bug_description' => '...description...',
280     'bug_status'      => 'NEW'
283 // Set all the column values at once
284 $newRow->setFromArray($data);
286 // INSERT the new row to the database
287 $newRow->save();
288 ]]></programlisting>
290             </example>
292         </sect3>
294         <sect3 id="zend.db.table.row.write.delete">
296             <title>Deleting a row</title>
298             <para> You can call the <methodname>delete()</methodname> method on
299                 a Row object. This deletes rows in the database matching the
300                 primary key in the Row object. </para>
302             <example id="zend.db.table.row.write.delete.example">
304                 <title>Example of deleting a row</title>
306                 <programlisting language="php"><![CDATA[
307 $bugs = new Bugs();
308 $row = $bugs->fetchRow('bug_id = 1');
310 // DELETE this row
311 $row->delete();
312 ]]></programlisting>
314             </example>
316             <para> You do not have to call <methodname>save()</methodname> to
317                 apply the delete; it is executed against the database
318                 immediately. </para>
320         </sect3>
322     </sect2>
324     <sect2 id="zend.db.table.row.serialize">
326         <title>Serializing and unserializing rows</title>
328         <para> It is often convenient to save the contents of a database row to
329             be used later. <emphasis>Serialization</emphasis> is the name for
330             the operation that converts an object into a form that is easy to
331             save in offline storage (for example, a file). Objects of type
332                 <classname>Zend_Db_Table_Row_Abstract</classname> are
333             serializable. </para>
335         <sect3 id="zend.db.table.row.serialize.serializing">
337             <title>Serializing a Row</title>
339             <para> Simply use <acronym>PHP</acronym> 's
340                     <methodname>serialize()</methodname> function to create a
341                 string containing a byte-stream representation of the Row object
342                 argument. </para>
344             <example id="zend.db.table.row.serialize.serializing.example">
346                 <title>Example of serializing a row</title>
348                 <programlisting language="php"><![CDATA[
349 $bugs = new Bugs();
350 $row = $bugs->fetchRow('bug_id = 1');
352 // Convert object to serialized form
353 $serializedRow = serialize($row);
355 // Now you can write $serializedRow to a file, etc.
356 ]]></programlisting>
358             </example>
360         </sect3>
362         <sect3 id="zend.db.table.row.serialize.unserializing">
364             <title>Unserializing Row Data</title>
366             <para> Use PHP's <methodname>unserialize()</methodname> function to
367                 restore a string containing a byte-stream representation of an
368                 object. The function returns the original object. </para>
370             <para> Note that the Row object returned is in a
371                     <emphasis>disconnected</emphasis> state. You can read the
372                 Row object and its properties, but you cannot change values in
373                 the Row or execute other methods that require a database
374                 connection (for example, queries against related tables). </para>
376             <example id="zend.db.table.row.serialize.unserializing.example">
378                 <title>Example of unserializing a serialized row</title>
380                 <programlisting language="php"><![CDATA[
381 $rowClone = unserialize($serializedRow);
383 // Now you can use object properties, but read-only
384 echo $rowClone->bug_description;
385 ]]></programlisting>
387             </example>
389             <note>
391                 <title>Why do Rows unserialize in a disconnected state?</title>
393                 <para>A serialized object is a string that is readable to anyone
394                     who possesses it. It could be a security risk to store
395                     parameters such as database account and password in plain,
396                     unencrypted text in the serialized string. You would not
397                     want to store such data to a text file that is not
398                     protected, or send it in an email or other medium that is
399                     easily read by potential attackers. The reader of the
400                     serialized object should not be able to use it to gain
401                     access to your database without knowing valid
402                     credentials.</para>
404             </note>
406         </sect3>
408         <sect3 id="zend.db.table.row.serialize.set-table">
410             <title>Reactivating a Row as Live Data</title>
412             <para> You can reactivate a disconnected Row, using the
413                     <methodname>setTable()</methodname> method. The argument to
414                 this method is a valid object of type
415                     <classname>Zend_Db_Table_Abstract</classname> , which you
416                 create. Creating a Table object requires a live connection to
417                 the database, so by reassociating the Table with the Row, the
418                 Row gains access to the database. Subsequently, you can change
419                 values in the Row object and save the changes to the database. </para>
421             <example id="zend.db.table.row.serialize.set-table.example">
423                 <title>Example of reactivating a row</title>
425                 <programlisting language="php"><![CDATA[
426 $rowClone = unserialize($serializedRow);
428 $bugs = new Bugs();
430 // Reconnect the row to a table, and
431 // thus to a live database connection
432 $rowClone->setTable($bugs);
434 // Now you can make changes to the row and save them
435 $rowClone->bug_status = 'FIXED';
436 $rowClone->save();
437 ]]></programlisting>
439             </example>
441         </sect3>
443     </sect2>
445     <sect2 id="zend.db.table.row.extending">
447         <title>Extending the Row class</title>
449         <para>
450             <classname>Zend_Db_Table_Row</classname> is the default concrete
451             class that extends <classname>Zend_Db_Table_Row_Abstract</classname>
452             . You can define your own concrete class for instances of Row by
453             extending <classname>Zend_Db_Table_Row_Abstract</classname> . To use
454             your new Row class to store results of Table queries, specify the
455             custom Row class by name either in the <varname>$_rowClass</varname>
456             protected member of a Table class, or in the array argument of the
457             constructor of a Table object. </para>
459         <example id="zend.db.table.row.extending.example">
461             <title>Specifying a custom Row class</title>
463             <programlisting language="php"><![CDATA[
464 class MyRow extends Zend_Db_Table_Row_Abstract
466     // ...customizations
469 // Specify a custom Row to be used by default
470 // in all instances of a Table class.
471 class Products extends Zend_Db_Table_Abstract
473     protected $_name = 'products';
474     protected $_rowClass = 'MyRow';
477 // Or specify a custom Row to be used in one
478 // instance of a Table class.
479 $bugs = new Bugs(array('rowClass' => 'MyRow'));
480 ]]></programlisting>
482         </example>
484         <sect3 id="zend.db.table.row.extending.overriding">
486             <title>Row initialization</title>
488             <para> If application-specific logic needs to be initialized when a
489                 row is constructed, you can select to move your tasks to the
490                     <methodname>init()</methodname> method, which is called
491                 after all row metadata has been processed. This is recommended
492                 over the <methodname>__construct</methodname> method if you do
493                 not need to alter the metadata in any programmatic way. <example
494                     id="zend.db.table.row.init.usage.example">
496                     <title>Example usage of init() method</title>
498                     <programlisting language="php"><![CDATA[
499 class MyApplicationRow extends Zend_Db_Table_Row_Abstract
501     protected $_role;
503     public function init()
504     {
505         $this->_role = new MyRoleClass();
506     }
508 ]]></programlisting>
510                 </example>
511             </para>
513         </sect3>
515         <sect3 id="zend.db.table.row.extending.insert-update">
517             <title>Defining Custom Logic for Insert, Update, and Delete in
518                 Zend_Db_Table_Row</title>
520             <para> The Row class calls protected methods
521                     <methodname>_insert()</methodname> ,
522                     <methodname>_update()</methodname> , and
523                     <methodname>_delete()</methodname> before performing the
524                 corresponding operations <methodname>INSERT</methodname> ,
525                     <methodname>UPDATE</methodname> , and
526                     <methodname>DELETE</methodname> . You can add logic to these
527                 methods in your custom Row subclass. </para>
529             <para> If you need to do custom logic in a specific table, and the
530                 custom logic must occur for every operation on that table, it
531                 may make more sense to implement your custom code in the
532                     <methodname>insert()</methodname> ,
533                     <methodname>update()</methodname> and
534                     <methodname>delete()</methodname> methods of your Table
535                 class. However, sometimes it may be necessary to do custom logic
536                 in the Row class. </para>
538             <para>Below are some example cases where it might make sense to
539                 implement custom logic in a Row class instead of in the Table
540                 class:</para>
542             <example id="zend.db.table.row.extending.overriding-example1">
544                 <title>Example of custom logic in a Row class</title>
546                 <para>The custom logic may not apply in all cases of operations
547                     on the respective Table. You can provide custom logic on
548                     demand by implementing it in a Row class and creating an
549                     instance of the Table class with that custom Row class
550                     specified. Otherwise, the Table uses the default Row
551                     class.</para>
553                 <para> You need data operations on this table to record the
554                     operation to a <classname>Zend_Log</classname> object, but
555                     only if the application configuration has enabled this
556                     behavior. </para>
558                 <programlisting language="php"><![CDATA[
559 class MyLoggingRow extends Zend_Db_Table_Row_Abstract
561     protected function _insert()
562     {
563         $log = Zend_Registry::get('database_log');
564         $log->info(Zend_Debug::dump($this->_data,
565                                     "INSERT: $this->_tableClass",
566                                     false)
567                   );
568     }
571 // $loggingEnabled is an example property that depends
572 // on your application configuration
573 if ($loggingEnabled) {
574     $bugs = new Bugs(array('rowClass' => 'MyLoggingRow'));
575 } else {
576     $bugs = new Bugs();
578 ]]></programlisting>
580             </example>
582             <example id="zend.db.table.row.extending.overriding-example2">
584                 <title>Example of a Row class that logs insert data for multiple
585                     tables</title>
587                 <para>The custom logic may be common to multiple tables. Instead
588                     of implementing the same custom logic in every one of your
589                     Table classes, you can implement the code for such actions
590                     in the definition of a Row class, and use this Row in each
591                     of your Table classes.</para>
593                 <para>In this example, the logging code is identical in all
594                     table classes.</para>
596                 <programlisting language="php"><![CDATA[
597 class MyLoggingRow extends Zend_Db_Table_Row_Abstract
599     protected function _insert()
600     {
601         $log = Zend_Registry::get('database_log');
602         $log->info(Zend_Debug::dump($this->_data,
603                                     "INSERT: $this->_tableClass",
604                                     false)
605                   );
606     }
609 class Bugs extends Zend_Db_Table_Abstract
611     protected $_name = 'bugs';
612     protected $_rowClass = 'MyLoggingRow';
615 class Products extends Zend_Db_Table_Abstract
617     protected $_name = 'products';
618     protected $_rowClass = 'MyLoggingRow';
620 ]]></programlisting>
622             </example>
624         </sect3>
626         <sect3 id="zend.db.table.row.extending.inflection">
628             <title>Define Inflection in Zend_Db_Table_Row</title>
630             <para> Some people prefer that the table class name match a table
631                 name in the <acronym>RDBMS</acronym> by using a string
632                 transformation called <emphasis>inflection</emphasis> . </para>
634             <para>
635                 <classname>Zend_Db</classname> classes do not implement
636                 inflection by default. See <xref
637                     linkend="zend.db.table.extending.inflection"/> for an
638                 explanation of this policy. </para>
640             <para> If you prefer to use inflection, then you must implement the
641                 transformation yourself, by overriding the
642                     <methodname>_transformColumn()</methodname> method in a
643                 custom Row class, and using that custom Row class when you
644                 perform queries against your Table class. </para>
646             <example id="zend.db.table.row.extending.inflection.example">
648                 <title>Example of defining an inflection transformation</title>
650                 <para> This allows you to use an inflected version of the column
651                     name in the accessors. The Row class uses the
652                         <methodname>_transformColumn()</methodname> method to
653                     change the name you use to the native column name in the
654                     database table. </para>
656                 <programlisting language="php"><![CDATA[
657 class MyInflectedRow extends Zend_Db_Table_Row_Abstract
659     protected function _transformColumn($columnName)
660     {
661         $nativeColumnName = myCustomInflector($columnName);
662         return $nativeColumnName;
663     }
666 class Bugs extends Zend_Db_Table_Abstract
668     protected $_name = 'bugs';
669     protected $_rowClass = 'MyInflectedRow';
672 $bugs = new Bugs();
673 $row = $bugs->fetchNew();
675 // Use camelcase column names, and rely on the
676 // transformation function to change it into the
677 // native representation.
678 $row->bugDescription = 'New description';
679 ]]></programlisting>
681             </example>
683             <para>You are responsible for writing the functions to perform
684                 inflection transformation. Zend Framework does not provide such
685                 a function.</para>
687         </sect3>
689     </sect2>
691 </sect1>