Zend_Db_Table_Row.xml 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- EN-Revision: 24249 -->
  3. <!-- Reviewed: no -->
  4. <sect1 id="zend.db.table.row">
  5. <title>Zend_Db_Table_Row</title>
  6. <sect2 id="zend.db.table.row.introduction">
  7. <title>Introducción</title>
  8. <para>
  9. <classname>Zend_Db_Table_Row</classname> is a class that contains an
  10. individual row of a <classname>Zend_Db_Table</classname> object.
  11. When you run a query against a Table class, the result is returned
  12. in a set of <classname>Zend_Db_Table_Row</classname> objects. You
  13. can also use this object to create new rows and add them to the
  14. database table. </para>
  15. <para>
  16. <classname>Zend_Db_Table_Row</classname> is an implementation of the
  17. <ulink
  18. url="http://www.martinfowler.com/eaaCatalog/rowDataGateway.html"
  19. >Row Data Gateway</ulink> pattern. </para>
  20. </sect2>
  21. <sect2 id="zend.db.table.row.read">
  22. <title>Fetching a Row</title>
  23. <para>
  24. <classname>Zend_Db_Table_Abstract</classname> provides methods
  25. <methodname>find()</methodname> and
  26. <methodname>fetchAll()</methodname> , which each return an
  27. object of type <classname>Zend_Db_Table_Rowset</classname> , and the
  28. method <methodname>fetchRow()</methodname> , which returns an object
  29. of type <classname>Zend_Db_Table_Row</classname> . </para>
  30. <example id="zend.db.table.row.read.example">
  31. <title>Example of fetching a row</title>
  32. <programlisting language="php"><![CDATA[
  33. $bugs = new Bugs();
  34. $row = $bugs->fetchRow($bugs->select()->where('bug_id = ?', 1));
  35. ]]></programlisting>
  36. </example>
  37. <para> A <classname>Zend_Db_Table_Rowset</classname> object contains a
  38. collection of <classname>Zend_Db_Table_Row</classname> objects. See
  39. <xref linkend="zend.db.table.rowset"/> . </para>
  40. <example id="zend.db.table.row.read.example-rowset">
  41. <title>Example of reading a row in a rowset</title>
  42. <programlisting language="php"><![CDATA[
  43. $bugs = new Bugs();
  44. $rowset = $bugs->fetchAll($bugs->select()->where('bug_status = ?', 1));
  45. $row = $rowset->current();
  46. ]]></programlisting>
  47. </example>
  48. <sect3 id="zend.db.table.row.read.get">
  49. <title>Reading column values from a row</title>
  50. <para>
  51. <classname>Zend_Db_Table_Row_Abstract</classname> provides
  52. accessor methods so you can reference columns in the row as
  53. object properties. </para>
  54. <example id="zend.db.table.row.read.get.example">
  55. <title>Example of reading a column in a row</title>
  56. <programlisting language="php"><![CDATA[
  57. $bugs = new Bugs();
  58. $row = $bugs->fetchRow($bugs->select()->where('bug_id = ?', 1));
  59. // Echo the value of the bug_description column
  60. echo $row->bug_description;
  61. ]]></programlisting>
  62. </example>
  63. <note>
  64. <para> Earlier versions of
  65. <classname>Zend_Db_Table_Row</classname> mapped these
  66. column accessors to the database column names using a string
  67. transformation called <emphasis>inflection</emphasis> . </para>
  68. <para> Currently, <classname>Zend_Db_Table_Row</classname> does
  69. not implement inflection. Accessed property names need to
  70. match the spelling of the column names as they appear in
  71. your database. </para>
  72. </note>
  73. </sect3>
  74. <sect3 id="zend.db.table.row.read.to-array">
  75. <title>Retrieving Row Data as an Array</title>
  76. <para> You can access the row's data as an array using the
  77. <methodname>toArray()</methodname> method of the Row object.
  78. This returns an associative array of the column names to the
  79. column values. </para>
  80. <example id="zend.db.table.row.read.to-array.example">
  81. <title>Example of using the toArray() method</title>
  82. <programlisting language="php"><![CDATA[
  83. $bugs = new Bugs();
  84. $row = $bugs->fetchRow($bugs->select()->where('bug_id = ?', 1));
  85. // Get the column/value associative array from the Row object
  86. $rowArray = $row->toArray();
  87. // Now use it as a normal array
  88. foreach ($rowArray as $column => $value) {
  89. echo "Column: $column\n";
  90. echo "Value: $value\n";
  91. }
  92. ]]></programlisting>
  93. </example>
  94. <para> The array returned from <methodname>toArray()</methodname> is
  95. not updateable. You can modify values in the array as you can
  96. with any array, but you cannot save changes to this array to the
  97. database directly. </para>
  98. </sect3>
  99. <sect3 id="zend.db.table.row.read.relationships">
  100. <title>Fetching data from related tables</title>
  101. <para> The <classname>Zend_Db_Table_Row_Abstract</classname> class
  102. provides methods for fetching rows and rowsets from related
  103. tables. See <xref linkend="zend.db.table.relationships"/> for
  104. more information on table relationships. </para>
  105. </sect3>
  106. </sect2>
  107. <sect2 id="zend.db.table.row.write">
  108. <title>Writing rows to the database</title>
  109. <sect3 id="zend.db.table.row.write.set">
  110. <title>Changing column values in a row</title>
  111. <para>You can set individual column values using column accessors,
  112. similar to how the columns are read as object properties in the
  113. example above.</para>
  114. <para> Using a column accessor to set a value changes the column
  115. value of the row object in your application, but it does not
  116. commit the change to the database yet. You can do that with the
  117. <methodname>save()</methodname> method. </para>
  118. <example id="zend.db.table.row.write.set.example">
  119. <title>Example of changing a column in a row</title>
  120. <programlisting language="php"><![CDATA[
  121. $bugs = new Bugs();
  122. $row = $bugs->fetchRow($bugs->select()->where('bug_id = ?', 1));
  123. // Change the value of one or more columns
  124. $row->bug_status = 'FIXED';
  125. // UPDATE the row in the database with new values
  126. $row->save();
  127. ]]></programlisting>
  128. </example>
  129. </sect3>
  130. <sect3 id="zend.db.table.row.write.insert">
  131. <title>Inserting a new row</title>
  132. <para> You can create a new row for a given table with the
  133. <methodname>createRow()</methodname> method of the table
  134. class. You can access fields of this row with the
  135. object-oriented interface, but the row is not stored in the
  136. database until you call the <methodname>save()</methodname>
  137. method. </para>
  138. <example id="zend.db.table.row.write.insert.example">
  139. <title>Example of creating a new row for a table</title>
  140. <programlisting language="php"><![CDATA[
  141. $bugs = new Bugs();
  142. $newRow = $bugs->createRow();
  143. // Set column values as appropriate for your application
  144. $newRow->bug_description = '...description...';
  145. $newRow->bug_status = 'NEW';
  146. // INSERT the new row to the database
  147. $newRow->save();
  148. ]]></programlisting>
  149. </example>
  150. <para>The optional argument to the createRow() method is an
  151. associative array, with which you can populate fields of the new
  152. row.</para>
  153. <example id="zend.db.table.row.write.insert.example2">
  154. <title>Example of populating a new row for a table</title>
  155. <programlisting language="php"><![CDATA[
  156. $data = array(
  157. 'bug_description' => '...description...',
  158. 'bug_status' => 'NEW'
  159. );
  160. $bugs = new Bugs();
  161. $newRow = $bugs->createRow($data);
  162. // INSERT the new row to the database
  163. $newRow->save();
  164. ]]></programlisting>
  165. </example>
  166. <note>
  167. <para> The <methodname>createRow()</methodname> method was
  168. called <methodname>fetchNew()</methodname> in earlier
  169. releases of <classname>Zend_Db_Table</classname> . You are
  170. encouraged to use the new method name, even though the old
  171. name continues to work for the sake of backward
  172. compatibility. </para>
  173. </note>
  174. </sect3>
  175. <sect3 id="zend.db.table.row.write.set-from-array">
  176. <title>Changing values in multiple columns</title>
  177. <para>
  178. <classname>Zend_Db_Table_Row_Abstract</classname> provides the
  179. <methodname>setFromArray()</methodname> method to enable you
  180. to set several columns in a single row at once, specified in an
  181. associative array that maps the column names to values. You may
  182. find this method convenient for setting values both for new rows
  183. and for rows you need to update. </para>
  184. <example id="zend.db.table.row.write.set-from-array.example">
  185. <title>Example of using setFromArray() to set values in a new
  186. Row</title>
  187. <programlisting language="php"><![CDATA[
  188. $bugs = new Bugs();
  189. $newRow = $bugs->createRow();
  190. // Data are arranged in an associative array
  191. $data = array(
  192. 'bug_description' => '...description...',
  193. 'bug_status' => 'NEW'
  194. );
  195. // Set all the column values at once
  196. $newRow->setFromArray($data);
  197. // INSERT the new row to the database
  198. $newRow->save();
  199. ]]></programlisting>
  200. </example>
  201. </sect3>
  202. <sect3 id="zend.db.table.row.write.delete">
  203. <title>Deleting a row</title>
  204. <para> You can call the <methodname>delete()</methodname> method on
  205. a Row object. This deletes rows in the database matching the
  206. primary key in the Row object. </para>
  207. <example id="zend.db.table.row.write.delete.example">
  208. <title>Example of deleting a row</title>
  209. <programlisting language="php"><![CDATA[
  210. $bugs = new Bugs();
  211. $row = $bugs->fetchRow('bug_id = 1');
  212. // DELETE this row
  213. $row->delete();
  214. ]]></programlisting>
  215. </example>
  216. <para> You do not have to call <methodname>save()</methodname> to
  217. apply the delete; it is executed against the database
  218. immediately. </para>
  219. </sect3>
  220. </sect2>
  221. <sect2 id="zend.db.table.row.serialize">
  222. <title>Serializing and unserializing rows</title>
  223. <para> It is often convenient to save the contents of a database row to
  224. be used later. <emphasis>Serialization</emphasis> is the name for
  225. the operation that converts an object into a form that is easy to
  226. save in offline storage (for example, a file). Objects of type
  227. <classname>Zend_Db_Table_Row_Abstract</classname> are
  228. serializable. </para>
  229. <sect3 id="zend.db.table.row.serialize.serializing">
  230. <title>Serializing a Row</title>
  231. <para> Simply use <acronym>PHP</acronym> 's
  232. <methodname>serialize()</methodname> function to create a
  233. string containing a byte-stream representation of the Row object
  234. argument. </para>
  235. <example id="zend.db.table.row.serialize.serializing.example">
  236. <title>Example of serializing a row</title>
  237. <programlisting language="php"><![CDATA[
  238. $bugs = new Bugs();
  239. $row = $bugs->fetchRow('bug_id = 1');
  240. // Convert object to serialized form
  241. $serializedRow = serialize($row);
  242. // Now you can write $serializedRow to a file, etc.
  243. ]]></programlisting>
  244. </example>
  245. </sect3>
  246. <sect3 id="zend.db.table.row.serialize.unserializing">
  247. <title>Unserializing Row Data</title>
  248. <para> Use PHP's <methodname>unserialize()</methodname> function to
  249. restore a string containing a byte-stream representation of an
  250. object. The function returns the original object. </para>
  251. <para> Note that the Row object returned is in a
  252. <emphasis>disconnected</emphasis> state. You can read the
  253. Row object and its properties, but you cannot change values in
  254. the Row or execute other methods that require a database
  255. connection (for example, queries against related tables). </para>
  256. <example id="zend.db.table.row.serialize.unserializing.example">
  257. <title>Example of unserializing a serialized row</title>
  258. <programlisting language="php"><![CDATA[
  259. $rowClone = unserialize($serializedRow);
  260. // Now you can use object properties, but read-only
  261. echo $rowClone->bug_description;
  262. ]]></programlisting>
  263. </example>
  264. <note>
  265. <title>Why do Rows unserialize in a disconnected state?</title>
  266. <para>A serialized object is a string that is readable to anyone
  267. who possesses it. It could be a security risk to store
  268. parameters such as database account and password in plain,
  269. unencrypted text in the serialized string. You would not
  270. want to store such data to a text file that is not
  271. protected, or send it in an email or other medium that is
  272. easily read by potential attackers. The reader of the
  273. serialized object should not be able to use it to gain
  274. access to your database without knowing valid
  275. credentials.</para>
  276. </note>
  277. </sect3>
  278. <sect3 id="zend.db.table.row.serialize.set-table">
  279. <title>Reactivating a Row as Live Data</title>
  280. <para> You can reactivate a disconnected Row, using the
  281. <methodname>setTable()</methodname> method. The argument to
  282. this method is a valid object of type
  283. <classname>Zend_Db_Table_Abstract</classname> , which you
  284. create. Creating a Table object requires a live connection to
  285. the database, so by reassociating the Table with the Row, the
  286. Row gains access to the database. Subsequently, you can change
  287. values in the Row object and save the changes to the database. </para>
  288. <example id="zend.db.table.row.serialize.set-table.example">
  289. <title>Example of reactivating a row</title>
  290. <programlisting language="php"><![CDATA[
  291. $rowClone = unserialize($serializedRow);
  292. $bugs = new Bugs();
  293. // Reconnect the row to a table, and
  294. // thus to a live database connection
  295. $rowClone->setTable($bugs);
  296. // Now you can make changes to the row and save them
  297. $rowClone->bug_status = 'FIXED';
  298. $rowClone->save();
  299. ]]></programlisting>
  300. </example>
  301. </sect3>
  302. </sect2>
  303. <sect2 id="zend.db.table.row.extending">
  304. <title>Extending the Row class</title>
  305. <para>
  306. <classname>Zend_Db_Table_Row</classname> is the default concrete
  307. class that extends <classname>Zend_Db_Table_Row_Abstract</classname>
  308. . You can define your own concrete class for instances of Row by
  309. extending <classname>Zend_Db_Table_Row_Abstract</classname> . To use
  310. your new Row class to store results of Table queries, specify the
  311. custom Row class by name either in the <varname>$_rowClass</varname>
  312. protected member of a Table class, or in the array argument of the
  313. constructor of a Table object. </para>
  314. <example id="zend.db.table.row.extending.example">
  315. <title>Specifying a custom Row class</title>
  316. <programlisting language="php"><![CDATA[
  317. class MyRow extends Zend_Db_Table_Row_Abstract
  318. {
  319. // ...customizations
  320. }
  321. // Specify a custom Row to be used by default
  322. // in all instances of a Table class.
  323. class Products extends Zend_Db_Table_Abstract
  324. {
  325. protected $_name = 'products';
  326. protected $_rowClass = 'MyRow';
  327. }
  328. // Or specify a custom Row to be used in one
  329. // instance of a Table class.
  330. $bugs = new Bugs(array('rowClass' => 'MyRow'));
  331. ]]></programlisting>
  332. </example>
  333. <sect3 id="zend.db.table.row.extending.overriding">
  334. <title>Row initialization</title>
  335. <para> If application-specific logic needs to be initialized when a
  336. row is constructed, you can select to move your tasks to the
  337. <methodname>init()</methodname> method, which is called
  338. after all row metadata has been processed. This is recommended
  339. over the <methodname>__construct</methodname> method if you do
  340. not need to alter the metadata in any programmatic way. <example
  341. id="zend.db.table.row.init.usage.example">
  342. <title>Example usage of init() method</title>
  343. <programlisting language="php"><![CDATA[
  344. class MyApplicationRow extends Zend_Db_Table_Row_Abstract
  345. {
  346. protected $_role;
  347. public function init()
  348. {
  349. $this->_role = new MyRoleClass();
  350. }
  351. }
  352. ]]></programlisting>
  353. </example>
  354. </para>
  355. </sect3>
  356. <sect3 id="zend.db.table.row.extending.insert-update">
  357. <title>Defining Custom Logic for Insert, Update, and Delete in
  358. Zend_Db_Table_Row</title>
  359. <para> The Row class calls protected methods
  360. <methodname>_insert()</methodname> ,
  361. <methodname>_update()</methodname> , and
  362. <methodname>_delete()</methodname> before performing the
  363. corresponding operations <methodname>INSERT</methodname> ,
  364. <methodname>UPDATE</methodname> , and
  365. <methodname>DELETE</methodname> . You can add logic to these
  366. methods in your custom Row subclass. </para>
  367. <para> If you need to do custom logic in a specific table, and the
  368. custom logic must occur for every operation on that table, it
  369. may make more sense to implement your custom code in the
  370. <methodname>insert()</methodname> ,
  371. <methodname>update()</methodname> and
  372. <methodname>delete()</methodname> methods of your Table
  373. class. However, sometimes it may be necessary to do custom logic
  374. in the Row class. </para>
  375. <para>Below are some example cases where it might make sense to
  376. implement custom logic in a Row class instead of in the Table
  377. class:</para>
  378. <example id="zend.db.table.row.extending.overriding-example1">
  379. <title>Example of custom logic in a Row class</title>
  380. <para>The custom logic may not apply in all cases of operations
  381. on the respective Table. You can provide custom logic on
  382. demand by implementing it in a Row class and creating an
  383. instance of the Table class with that custom Row class
  384. specified. Otherwise, the Table uses the default Row
  385. class.</para>
  386. <para> You need data operations on this table to record the
  387. operation to a <classname>Zend_Log</classname> object, but
  388. only if the application configuration has enabled this
  389. behavior. </para>
  390. <programlisting language="php"><![CDATA[
  391. class MyLoggingRow extends Zend_Db_Table_Row_Abstract
  392. {
  393. protected function _insert()
  394. {
  395. $log = Zend_Registry::get('database_log');
  396. $log->info(Zend_Debug::dump($this->_data,
  397. "INSERT: $this->_tableClass",
  398. false)
  399. );
  400. }
  401. }
  402. // $loggingEnabled is an example property that depends
  403. // on your application configuration
  404. if ($loggingEnabled) {
  405. $bugs = new Bugs(array('rowClass' => 'MyLoggingRow'));
  406. } else {
  407. $bugs = new Bugs();
  408. }
  409. ]]></programlisting>
  410. </example>
  411. <example id="zend.db.table.row.extending.overriding-example2">
  412. <title>Example of a Row class that logs insert data for multiple
  413. tables</title>
  414. <para>The custom logic may be common to multiple tables. Instead
  415. of implementing the same custom logic in every one of your
  416. Table classes, you can implement the code for such actions
  417. in the definition of a Row class, and use this Row in each
  418. of your Table classes.</para>
  419. <para>In this example, the logging code is identical in all
  420. table classes.</para>
  421. <programlisting language="php"><![CDATA[
  422. class MyLoggingRow extends Zend_Db_Table_Row_Abstract
  423. {
  424. protected function _insert()
  425. {
  426. $log = Zend_Registry::get('database_log');
  427. $log->info(Zend_Debug::dump($this->_data,
  428. "INSERT: $this->_tableClass",
  429. false)
  430. );
  431. }
  432. }
  433. class Bugs extends Zend_Db_Table_Abstract
  434. {
  435. protected $_name = 'bugs';
  436. protected $_rowClass = 'MyLoggingRow';
  437. }
  438. class Products extends Zend_Db_Table_Abstract
  439. {
  440. protected $_name = 'products';
  441. protected $_rowClass = 'MyLoggingRow';
  442. }
  443. ]]></programlisting>
  444. </example>
  445. </sect3>
  446. <sect3 id="zend.db.table.row.extending.inflection">
  447. <title>Define Inflection in Zend_Db_Table_Row</title>
  448. <para> Some people prefer that the table class name match a table
  449. name in the <acronym>RDBMS</acronym> by using a string
  450. transformation called <emphasis>inflection</emphasis> . </para>
  451. <para>
  452. <classname>Zend_Db</classname> classes do not implement
  453. inflection by default. See <xref
  454. linkend="zend.db.table.extending.inflection"/> for an
  455. explanation of this policy. </para>
  456. <para> If you prefer to use inflection, then you must implement the
  457. transformation yourself, by overriding the
  458. <methodname>_transformColumn()</methodname> method in a
  459. custom Row class, and using that custom Row class when you
  460. perform queries against your Table class. </para>
  461. <example id="zend.db.table.row.extending.inflection.example">
  462. <title>Example of defining an inflection transformation</title>
  463. <para> This allows you to use an inflected version of the column
  464. name in the accessors. The Row class uses the
  465. <methodname>_transformColumn()</methodname> method to
  466. change the name you use to the native column name in the
  467. database table. </para>
  468. <programlisting language="php"><![CDATA[
  469. class MyInflectedRow extends Zend_Db_Table_Row_Abstract
  470. {
  471. protected function _transformColumn($columnName)
  472. {
  473. $nativeColumnName = myCustomInflector($columnName);
  474. return $nativeColumnName;
  475. }
  476. }
  477. class Bugs extends Zend_Db_Table_Abstract
  478. {
  479. protected $_name = 'bugs';
  480. protected $_rowClass = 'MyInflectedRow';
  481. }
  482. $bugs = new Bugs();
  483. $row = $bugs->fetchNew();
  484. // Use camelcase column names, and rely on the
  485. // transformation function to change it into the
  486. // native representation.
  487. $row->bugDescription = 'New description';
  488. ]]></programlisting>
  489. </example>
  490. <para>You are responsible for writing the functions to perform
  491. inflection transformation. Zend Framework does not provide such
  492. a function.</para>
  493. </sect3>
  494. </sect2>
  495. </sect1>