File: Zend_Db_Table_Row.xml

package info (click to toggle)
zendframework 1.12.9%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: jessie-kfreebsd
  • size: 133,584 kB
  • sloc: xml: 1,311,829; php: 570,173; sh: 170; makefile: 125; sql: 121
file content (635 lines) | stat: -rw-r--r-- 24,462 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
<?xml version="1.0" encoding="UTF-8"?>
<!-- Reviewed: no -->
<sect1 id="zend.db.table.row">
    <title>Zend_Db_Table_Row</title>

    <sect2 id="zend.db.table.row.introduction">
        <title>Introduction</title>

        <para>
            <classname>Zend_Db_Table_Row</classname> is a class that contains an individual row of a
            <classname>Zend_Db_Table</classname> object. When you run a query against a Table class,
            the result is returned in a set of <classname>Zend_Db_Table_Row</classname> objects. You
            can also use this object to create new rows and add them to the database table.
        </para>

        <para>
            <classname>Zend_Db_Table_Row</classname> is an implementation of the <ulink
                url="http://www.martinfowler.com/eaaCatalog/rowDataGateway.html">Row Data
                Gateway</ulink> pattern.
        </para>
    </sect2>

    <sect2 id="zend.db.table.row.read">
        <title>Fetching a Row</title>

        <para>
            <classname>Zend_Db_Table_Abstract</classname> provides methods
            <methodname>find()</methodname> and <methodname>fetchAll()</methodname>, which each
            return an object of type <classname>Zend_Db_Table_Rowset</classname>, and the method
            <methodname>fetchRow()</methodname>, which returns an object of type
            <classname>Zend_Db_Table_Row</classname>.
        </para>

        <example id="zend.db.table.row.read.example">
            <title>Example of fetching a row</title>

            <programlisting language="php"><![CDATA[
$bugs = new Bugs();
$row = $bugs->fetchRow($bugs->select()->where('bug_id = ?', 1));
]]></programlisting>
        </example>

        <para>
            A <classname>Zend_Db_Table_Rowset</classname> object contains a collection of
            <classname>Zend_Db_Table_Row</classname> objects. See the chapter about <link
                linkend="zend.db.table.rowset">table rowset</link> for details.
        </para>

        <example id="zend.db.table.row.read.example-rowset">
            <title>Example of reading a row in a rowset</title>

            <programlisting language="php"><![CDATA[
$bugs = new Bugs();
$rowset = $bugs->fetchAll($bugs->select()->where('bug_status = ?', 1));
$row = $rowset->current();
]]></programlisting>
        </example>

        <sect3 id="zend.db.table.row.read.get">
            <title>Reading column values from a row</title>

            <para>
                <classname>Zend_Db_Table_Row_Abstract</classname> provides accessor methods so you
                can reference columns in the row as object properties.
            </para>

            <example id="zend.db.table.row.read.get.example">
                <title>Example of reading a column in a row</title>

                <programlisting language="php"><![CDATA[
$bugs = new Bugs();
$row = $bugs->fetchRow($bugs->select()->where('bug_id = ?', 1));

// Echo the value of the bug_description column
echo $row->bug_description;
]]></programlisting>
            </example>

            <note>
                <para>
                    Earlier versions of <classname>Zend_Db_Table_Row</classname> mapped these column
                    accessors to the database column names using a string transformation called
                    <emphasis>inflection</emphasis>.
                </para>

                <para>
                    Currently, <classname>Zend_Db_Table_Row</classname> does not implement
                    inflection. Accessed property names need to match the spelling of the column
                    names as they appear in your database.
                </para>
            </note>
        </sect3>

        <sect3 id="zend.db.table.row.read.to-array">
            <title>Retrieving Row Data as an Array</title>

            <para>
                You can access the row's data as an array using the
                <methodname>toArray()</methodname> method of the Row object. This returns an
                associative array of the column names to the column values.
            </para>

            <example id="zend.db.table.row.read.to-array.example">
                <title>Example of using the toArray() method</title>

                <programlisting language="php"><![CDATA[
$bugs = new Bugs();
$row = $bugs->fetchRow($bugs->select()->where('bug_id = ?', 1));

// Get the column/value associative array from the Row object
$rowArray = $row->toArray();

// Now use it as a normal array
foreach ($rowArray as $column => $value) {
    echo "Column: $column\n";
    echo "Value:  $value\n";
}
]]></programlisting>
            </example>

            <para>
                The array returned from <methodname>toArray()</methodname> is not updateable. You
                can modify values in the array as you can with any array, but you cannot save
                changes to this array to the database directly.
            </para>
        </sect3>

        <sect3 id="zend.db.table.row.read.relationships">
            <title>Fetching data from related tables</title>

            <para>
                The <classname>Zend_Db_Table_Row_Abstract</classname> class provides methods for
                fetching rows and rowsets from related tables. See the <link
                    linkend="zend.db.table.relationships">relationship chapter</link> for more
                information on table relationships.
            </para>
        </sect3>
    </sect2>

    <sect2 id="zend.db.table.row.write">
        <title>Writing rows to the database</title>

        <sect3 id="zend.db.table.row.write.set">
            <title>Changing column values in a row</title>

            <para>
                You can set individual column values using column accessors, similar to how the
                columns are read as object properties in the example above.
            </para>

            <para>
                Using a column accessor to set a value changes the column value of the row object
                in your application, but it does not commit the change to the database yet. You can
                do that with the <methodname>save()</methodname> method.
            </para>

            <example id="zend.db.table.row.write.set.example">
                <title>Example of changing a column in a row</title>

                <programlisting language="php"><![CDATA[
$bugs = new Bugs();
$row = $bugs->fetchRow($bugs->select()->where('bug_id = ?', 1));

// Change the value of one or more columns
$row->bug_status = 'FIXED';

// UPDATE the row in the database with new values
$row->save();
]]></programlisting>
            </example>
        </sect3>

        <sect3 id="zend.db.table.row.write.insert">
            <title>Inserting a new row</title>

            <para>
                You can create a new row for a given table with the
                <methodname>createRow()</methodname> method of the table class. You can access
                fields of this row with the object-oriented interface, but the row is not stored in
                the database until you call the <methodname>save()</methodname> method.
            </para>

            <example id="zend.db.table.row.write.insert.example">
                <title>Example of creating a new row for a table</title>

                <programlisting language="php"><![CDATA[
$bugs = new Bugs();
$newRow = $bugs->createRow();

// Set column values as appropriate for your application
$newRow->bug_description = '...description...';
$newRow->bug_status = 'NEW';

// INSERT the new row to the database
$newRow->save();
]]></programlisting>
            </example>

            <para>
                The optional argument to the <methodname>createRow()</methodname> method is an
                associative array, with which you can populate fields of the new row.
            </para>

            <example id="zend.db.table.row.write.insert.example2">
                <title>Example of populating a new row for a table</title>

                <programlisting language="php"><![CDATA[
$data = array(
    'bug_description' => '...description...',
    'bug_status'      => 'NEW'
);

$bugs = new Bugs();
$newRow = $bugs->createRow($data);

// INSERT the new row to the database
$newRow->save();
]]></programlisting>
            </example>

            <note>
                <para>
                    The <methodname>createRow()</methodname> method was called
                    <methodname>fetchNew()</methodname> in earlier releases of
                    <classname>Zend_Db_Table</classname>. You are encouraged to use the new method
                    name, even though the old name continues to work for the sake of backward
                    compatibility.
                </para>
            </note>
        </sect3>

        <sect3 id="zend.db.table.row.write.set-from-array">
            <title>Changing values in multiple columns</title>

            <para>
                <classname>Zend_Db_Table_Row_Abstract</classname> provides the
                <methodname>setFromArray()</methodname> method to enable you to set several columns
                in a single row at once, specified in an associative array that maps the column
                names to values. You may find this method convenient for setting values both for new
                rows and for rows you need to update.
            </para>

            <example id="zend.db.table.row.write.set-from-array.example">
                <title>Example of using setFromArray() to set values in a new Row</title>

                <programlisting language="php"><![CDATA[
$bugs = new Bugs();
$newRow = $bugs->createRow();

// Data are arranged in an associative array
$data = array(
    'bug_description' => '...description...',
    'bug_status'      => 'NEW'
);

// Set all the column values at once
$newRow->setFromArray($data);

// INSERT the new row to the database
$newRow->save();
]]></programlisting>
            </example>
        </sect3>

        <sect3 id="zend.db.table.row.write.delete">
            <title>Deleting a row</title>

            <para>
                You can call the <methodname>delete()</methodname> method on a Row object. This
                deletes rows in the database matching the primary key in the Row object.
            </para>

            <example id="zend.db.table.row.write.delete.example">
                <title>Example of deleting a row</title>

                <programlisting language="php"><![CDATA[
$bugs = new Bugs();
$row = $bugs->fetchRow('bug_id = 1');

// DELETE this row
$row->delete();
]]></programlisting>
            </example>

            <para>
                You do not have to call <methodname>save()</methodname> to apply the delete; it is
                executed against the database immediately.
            </para>
        </sect3>
    </sect2>

    <sect2 id="zend.db.table.row.serialize">
        <title>Serializing and unserializing rows</title>

        <para>
            It is often convenient to save the contents of a database row to be used later.
            <emphasis>Serialization</emphasis> is the name for the operation that converts an
            object into a form that is easy to save in offline storage (for example, a file).
            Objects of type <classname>Zend_Db_Table_Row_Abstract</classname> are serializable.
        </para>

        <sect3 id="zend.db.table.row.serialize.serializing">
            <title>Serializing a Row</title>

            <para>
                Simply use <acronym>PHP</acronym>'s <methodname>serialize()</methodname> function to
                create a string containing a byte-stream representation of the Row object argument.
            </para>

            <example id="zend.db.table.row.serialize.serializing.example">
                <title>Example of serializing a row</title>

                <programlisting language="php"><![CDATA[
$bugs = new Bugs();
$row = $bugs->fetchRow('bug_id = 1');

// Convert object to serialized form
$serializedRow = serialize($row);

// Now you can write $serializedRow to a file, etc.
]]></programlisting>
            </example>
        </sect3>

        <sect3 id="zend.db.table.row.serialize.unserializing">
            <title>Unserializing Row Data</title>

            <para>
                Use <acronym>PHP</acronym>'s <methodname>unserialize()</methodname> function to
                restore a string containing a byte-stream representation of an object. The function
                returns the original object.
            </para>

            <para>
                Note that the Row object returned is in a <emphasis>disconnected</emphasis> state.
                You can read the Row object and its properties, but you cannot change values in the
                Row or execute other methods that require a database connection (for example,
                queries against related tables).
            </para>

            <example id="zend.db.table.row.serialize.unserializing.example">
                <title>Example of unserializing a serialized row</title>

                <programlisting language="php"><![CDATA[
$rowClone = unserialize($serializedRow);

// Now you can use object properties, but read-only
echo $rowClone->bug_description;
]]></programlisting>
            </example>

            <note>
                <title>Why do Rows unserialize in a disconnected state?</title>

                <para>
                    A serialized object is a string that is readable to anyone who possesses it. It
                    could be a security risk to store parameters such as database account and
                    password in plain, unencrypted text in the serialized string. You would not
                    want to store such data to a text file that is not protected, or send it in an
                    email or other medium that is easily read by potential attackers. The reader of
                    the serialized object should not be able to use it to gain access to your
                    database without knowing valid credentials.
                </para>
            </note>
        </sect3>

        <sect3 id="zend.db.table.row.serialize.set-table">
            <title>Reactivating a Row as Live Data</title>

            <para>
                You can reactivate a disconnected Row, using the <methodname>setTable()</methodname>
                method. The argument to this method is a valid object of type
                <classname>Zend_Db_Table_Abstract</classname>, which you create. Creating a Table
                object requires a live connection to the database, so by reassociating the Table
                with the Row, the Row gains access to the database. Subsequently, you can change
                values in the Row object and save the changes to the database.
            </para>

            <example id="zend.db.table.row.serialize.set-table.example">
                <title>Example of reactivating a row</title>

                <programlisting language="php"><![CDATA[
$rowClone = unserialize($serializedRow);

$bugs = new Bugs();

// Reconnect the row to a table, and
// thus to a live database connection
$rowClone->setTable($bugs);

// Now you can make changes to the row and save them
$rowClone->bug_status = 'FIXED';
$rowClone->save();
]]></programlisting>
            </example>
        </sect3>
    </sect2>

    <sect2 id="zend.db.table.row.extending">
        <title>Extending the Row class</title>

        <para>
            <classname>Zend_Db_Table_Row</classname> is the default concrete class that extends
            <classname>Zend_Db_Table_Row_Abstract</classname>. You can define your own concrete
            class for instances of Row by extending
            <classname>Zend_Db_Table_Row_Abstract</classname>. To use your new Row class to store
            results of Table queries, specify the custom Row class by name either in the
            <varname>$_rowClass</varname> protected member of a Table class, or in the array
            argument of the constructor of a Table object.
        </para>

        <example id="zend.db.table.row.extending.example">
            <title>Specifying a custom Row class</title>

            <programlisting language="php"><![CDATA[
class MyRow extends Zend_Db_Table_Row_Abstract
{
    // ...customizations
}

// Specify a custom Row to be used by default
// in all instances of a Table class.
class Products extends Zend_Db_Table_Abstract
{
    protected $_name = 'products';
    protected $_rowClass = 'MyRow';
}

// Or specify a custom Row to be used in one
// instance of a Table class.
$bugs = new Bugs(array('rowClass' => 'MyRow'));
]]></programlisting>
        </example>

        <sect3 id="zend.db.table.row.extending.overriding">
            <title>Row initialization</title>

            <para>
                If application-specific logic needs to be initialized when a row is constructed,
                you can select to move your tasks to the <methodname>init()</methodname> method,
                which is called after all row metadata has been processed. This is recommended over
                the <methodname>__construct()</methodname> method if you do not need to alter the
                metadata in any programmatic way.
            </para>

            <example id="zend.db.table.row.init.usage.example">
                <title>Example usage of init() method</title>

                <programlisting language="php"><![CDATA[
class MyApplicationRow extends Zend_Db_Table_Row_Abstract
{
    protected $_role;

    public function init()
    {
        $this->_role = new MyRoleClass();
    }
}
]]></programlisting>
            </example>
        </sect3>

        <sect3 id="zend.db.table.row.extending.insert-update">
            <title>Defining Custom Logic for Insert, Update, and Delete in Zend_Db_Table_Row</title>

            <para>
                The Row class calls protected methods <methodname>_insert()</methodname>,
                <methodname>_update()</methodname>, and <methodname>_delete()</methodname> before
                performing the corresponding operations <constant>INSERT</constant>,
                <constant>UPDATE</constant>, and <constant>DELETE</constant>. You can add logic to
                these methods in your custom Row subclass.
            </para>

            <para>
                If you need to do custom logic in a specific table, and the custom logic must occur
                for every operation on that table, it may make more sense to implement your custom
                code in the <methodname>insert()</methodname>, <methodname>update()</methodname> and
                <methodname>delete()</methodname> methods of your Table class. However, sometimes it
                may be necessary to do custom logic in the Row class.
            </para>

            <para>
                Below are some example cases where it might make sense to implement custom logic in
                a Row class instead of in the Table class:
            </para>

            <example id="zend.db.table.row.extending.overriding-example1">
                <title>Example of custom logic in a Row class</title>

                <para>
                    The custom logic may not apply in all cases of operations on the respective
                    Table. You can provide custom logic on demand by implementing it in a Row class
                    and creating an instance of the Table class with that custom Row class
                    specified. Otherwise, the Table uses the default Row class.
                </para>

                <para>
                    You need data operations on this table to record the operation to a
                    <classname>Zend_Log</classname> object, but only if the application
                    configuration has enabled this behavior.
                </para>

                <programlisting language="php"><![CDATA[
class MyLoggingRow extends Zend_Db_Table_Row_Abstract
{
    protected function _insert()
    {
        $log = Zend_Registry::get('database_log');
        $log->info(Zend_Debug::dump($this->_data,
                                    "INSERT: $this->_tableClass",
                                    false)
                  );
    }
}

// $loggingEnabled is an example property that depends
// on your application configuration
if ($loggingEnabled) {
    $bugs = new Bugs(array('rowClass' => 'MyLoggingRow'));
} else {
    $bugs = new Bugs();
}
]]></programlisting>
            </example>

            <example id="zend.db.table.row.extending.overriding-example2">
                <title>Example of a Row class that logs insert data for multiple tables</title>

                <para>
                    The custom logic may be common to multiple tables. Instead of implementing the
                    same custom logic in every one of your Table classes, you can implement the
                    code for such actions in the definition of a Row class, and use this Row in
                    each of your Table classes.
                </para>

                <para>
                    In this example, the logging code is identical in all table classes.
                </para>

                <programlisting language="php"><![CDATA[
class MyLoggingRow extends Zend_Db_Table_Row_Abstract
{
    protected function _insert()
    {
        $log = Zend_Registry::get('database_log');
        $log->info(Zend_Debug::dump($this->_data,
                                    "INSERT: $this->_tableClass",
                                    false)
                  );
    }
}

class Bugs extends Zend_Db_Table_Abstract
{
    protected $_name = 'bugs';
    protected $_rowClass = 'MyLoggingRow';
}

class Products extends Zend_Db_Table_Abstract
{
    protected $_name = 'products';
    protected $_rowClass = 'MyLoggingRow';
}
]]></programlisting>
            </example>
        </sect3>

        <sect3 id="zend.db.table.row.extending.inflection">
            <title>Define Inflection in Zend_Db_Table_Row</title>

            <para>
                Some people prefer that the table class name match a table name in the
                <acronym>RDBMS</acronym> by using a string transformation called
                <emphasis>inflection</emphasis>.
            </para>

            <para>
                <classname>Zend_Db</classname> classes do not implement inflection by default. See
                the chapter about <link linkend="zend.db.table.extending.inflection">extending
                    inflection</link> for an explanation of this policy.
            </para>

            <para>
                If you prefer to use inflection, then you must implement the transformation
                yourself, by overriding the <methodname>_transformColumn()</methodname> method in a
                custom Row class, and using that custom Row class when you perform queries against
                your Table class.
            </para>

            <example id="zend.db.table.row.extending.inflection.example">
                <title>Example of defining an inflection transformation</title>

                <para>
                    This allows you to use an inflected version of the column name in the
                    accessors. The Row class uses the <methodname>_transformColumn()</methodname>
                    method to change the name you use to the native column name in the database
                    table.
                </para>

                <programlisting language="php"><![CDATA[
class MyInflectedRow extends Zend_Db_Table_Row_Abstract
{
    protected function _transformColumn($columnName)
    {
        $nativeColumnName = myCustomInflector($columnName);
        return $nativeColumnName;
    }
}

class Bugs extends Zend_Db_Table_Abstract
{
    protected $_name = 'bugs';
    protected $_rowClass = 'MyInflectedRow';
}

$bugs = new Bugs();
$row = $bugs->fetchNew();

// Use camelcase column names, and rely on the
// transformation function to change it into the
// native representation.
$row->bugDescription = 'New description';
]]></programlisting>
            </example>

            <para>
                You are responsible for writing the functions to perform inflection transformation.
                Zend Framework does not provide such a function.
            </para>
        </sect3>
    </sect2>
</sect1>
<!--
vim:se ts=4 sw=4 et:
-->