Zend_Db_Table_Row.xml 24 KB

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