Zend_Db_Table_Row.xml 23 KB

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