[MANUAL] English:
[zend.git] / documentation / manual / ru / module_specs / Zend_Db_Table_Row.xml
blob4443f3f2f0fa7b6e8e0d333df16e7b226d679aa2
1 <sect1 id="zend.db.table.row">
3     <title>Zend_Db_Table_Row</title>
5     <sect2 id="zend.db.table.row.introduction">
7         <title>Введение</title>
9         <para>
10             Zend_Db_Table_Row является классом, содержащим отдельную строку
11             объекта Zend_Db_Table. Когда вы производите запрос через класс
12             таблицы, результат возвращается в виде набора объектов
13             Zend_Db_Table_Row. Вы можете также использовать этот объект для
14             создания новых строк и их добавления в таблицу БД.
15         </para>
17         <para>
18             Zend_Db_Table_Row является реализацией паттерна
19             <ulink url="http://www.martinfowler.com/eaaCatalog/rowDataGateway.html">Row Data Gateway</ulink>.
20         </para>
22     </sect2>
24     <sect2 id="zend.db.table.row.read">
26         <title>Извлечение строки</title>
28         <para>
29             Zend_Db_Table_Abstract предоставляет методы <code>find()</code> и
30             <code>fetchAll()</code>, которые возвращают объект типа
31             Zend_Db_Table_Rowset, и метод <code>fetchRow()</code>, возвращающий
32             объект типа Zend_Db_Table_Row.
33         </para>
35         <example id="zend.db.table.row.read.example">
37             <title>Пример извлечения строки</title>
39             <programlisting language="php"><![CDATA[
40 $bugs = new Bugs();
41 $row = $bugs->fetchRow($bugs->select()->where('bug_id = ?', 1));
42 ]]>
43             </programlisting>
45         </example>
47         <para>
48             Объект Zend_Db_Table_Rowset содержит коллекцию объектов
49             Zend_Db_Table_Row. Для получения более подробной информации
50             читайте <xref linkend="zend.db.table.rowset" />.
51         </para>
53         <example id="zend.db.table.row.read.example-rowset">
55             <title>Пример получения строки из набора строк</title>
57             <programlisting language="php"><![CDATA[
58 $bugs = new Bugs();
59 $rowset = $bugs->fetchAll($bugs->select()->where('bug_status = ?', 1));
60 $row = $rowset->current();
61 ]]>
62             </programlisting>
64         </example>
66         <sect3 id="zend.db.table.row.read.get">
67             <title>Чтение значений столбцов из строки</title>
69             <para>
70                 Zend_Db_Table_Row_Abstract предоставляет методы-аксессоры,
71                 благодаря которым можно ссылаться на столбцы в строке как на
72                 свойства объекта.
73             </para>
75             <example id="zend.db.table.row.read.get.example">
77                 <title>Пример чтения столбца из строки</title>
79                 <programlisting language="php"><![CDATA[
80 $bugs = new Bugs();
81 $row = $bugs->fetchRow($bugs->select()->where('bug_id = ?', 1));
83 // Вывод значения столбца bug_description
84 echo $row->bug_description;
85 ]]>
86                 </programlisting>
88             </example>
90             <note>
92                 <para>
93                     Более ранние версии Zend_Db_Table_Row сопоставляли
94                     аксессоры столбцов и имена столбцов в БД с использованием
95                     преобразования строк, называемым
96                     <emphasis>инфлекцией</emphasis>.
97                 </para>
99                 <para>
100                     Zend_Db_Table_Row в его текущей реализации не использует
101                     инфлекцию. Написание аксессоров столбцов должно в точности
102                     соответствовать именам столбцов, так, как они представлены в
103                     БД.
104                 </para>
106             </note>
108         </sect3>
110         <sect3 id="zend.db.table.row.read.to-array">
112             <title>Получение данных строки в виде массива</title>
114             <para>
115                 Вы можете получать данные строки, используя метод
116                 <code>toArray()</code> объекта строки. Метод возвращает
117                 ассоциативный массив имен столбцов и их значений.
118             </para>
120             <example id="zend.db.table.row.read.to-array.example">
122                 <title>Пример использования метода toArray()</title>
124                 <programlisting language="php"><![CDATA[
125 $bugs = new Bugs();
126 $row = $bugs->fetchRow($bugs->select()->where('bug_id = ?', 1));
128 // Получение ассоциативного массива столбцов и их значений из объекта Row
129 $rowArray = $row->toArray();
131 // Теперь используется как обычный массив
132 foreach ($rowArray as $column => $value) {
133     echo "Column: $column\n";
134     echo "Value:  $value\n";
137                 </programlisting>
139             </example>
141             <para>
142                 Массив, возвращаемый методом <code>toArray()</code> не может
143                 использоваться для обновления данных в БД. Мы можете изменять
144                 значения в этом массиве так же, как и в любом другом массиве, но
145                 не можете сохранять измененные значения непосредственно из этого
146                 массива в БД.
147             </para>
149         </sect3>
151         <sect3 id="zend.db.table.row.read.relationships">
153             <title>Извлечение данных из связанных таблиц</title>
155             <para>
156                 Класс Zend_Db_Table_Row_Abstract предоставляет методы для
157                 извлечения строк и наборов строк из связанных таблиц.
158                 Читайте <xref linkend="zend.db.table.relationships" /> для
159                 получения более подробной информации о связях между таблицами.
160             </para>
162         </sect3>
164     </sect2>
166     <sect2 id="zend.db.table.row.write">
168         <title>Редактирование строк в БД</title>
170         <sect3 id="zend.db.table.row.write.set">
172             <title>Изменение значений столбцов в строке</title>
174             <para>
175                 Используя аксессоры столбцов, вы можете устанавливать значения
176                 отдельных столбцов по аналогии с чтением, т.е. так же, как если
177                 бы они были свойствами объекта.
178             </para>
180             <para>
181                 Использование аксессоров столбцов для установки значений
182                 изменяет значения столбцов в данном объекте строки, но
183                 эти изменения еще не фиксируются в БД. Вы можете произвести
184                 фиксацию через метод <code>save()</code>.
185             </para>
187             <example id="zend.db.table.row.write.set.example">
189                 <title>Пример изменения значения столбца в строке</title>
191                 <programlisting language="php"><![CDATA[
192 $bugs = new Bugs();
193 $row = $bugs->fetchRow($bugs->select()->where('bug_id = ?', 1));
195 // Изменение значения одного или более столбцов
196 $row->bug_status = 'FIXED';
198 // Обновление строки в БД с новыми значениями
199 $row->save();
201                 </programlisting>
203             </example>
205         </sect3>
207         <sect3 id="zend.db.table.row.write.insert">
209             <title>Вставка новой строки</title>
211             <para>
212                 Вы можете создавать новые строки для определенной таблицы с
213                 помощью метода <code>createRow()</code> класса таблицы. Можно
214                 работать с полями этой строки через объектно-ориентированный
215                 интерфейс, но строка не сохраняется в БД до тех пор, пока вы не
216                 вызовете метод <code>save()</code>.
217             </para>
219             <example id="zend.db.table.row.write.insert.example">
221                 <title>Пример создания новой строки таблицы</title>
223                 <programlisting language="php"><![CDATA[
224 $bugs = new Bugs();
225 $newRow = $bugs->createRow();
227 // Установка значений столбцов
228 $newRow->bug_description = '...description...';
229 $newRow->bug_status = 'NEW';
231 // Вставка новой строки в БД
232 $newRow->save();
234                 </programlisting>
235             </example>
237             <para>
238                 Опциональный аргумент метода является ассоциативным массивом,
239                 через который вы можете заполнить поля новой строки.
240             </para>
242             <example id="zend.db.table.row.write.insert.example2">
244                 <title>Пример заполнения новой строки для таблицы</title>
246                 <programlisting language="php"><![CDATA[
247 $data = array(
248     'bug_description' => '...description...',
249     'bug_status'      => 'NEW'
252 $bugs = new Bugs();
253 $newRow = $bugs->createRow($data);
255 // вставка новой строки в БД
256 $newRow->save();
258                 </programlisting>
260             </example>
262             <note>
263                 <para>
264                     В более ранних релизах Zend_Db_Table метод
265                     <code>createRow()</code> назывался <code>fetchNew()</code>.
266                     Мы рекомендуем использовать новое имя метода,
267                     несмотря на то, что старое имя метода по-прежнему работает
268                     в целях обеспечения обратной совместимости.
269                 </para>
270             </note>
272         </sect3>
274         <sect3 id="zend.db.table.row.write.set-from-array">
276             <title>Изменение значений в нескольких столбцах</title>
278             <para>
279                 Zend_Db_Table_Row_Abstract предоставляет метод
280                 <code>setFromArray()</code> для того, чтобы можно было
281                 устанавливать значения нескольких столбцов одновременно,
282                 определив ассоциативный массив имен столбцов и их значений.
283                 Этот метод может быть удобным как при создании новых строк, так
284                 и при обновлении существующих.
285             </para>
287             <example id="zend.db.table.row.write.set-from-array.example">
289                 <title>Пример использования метода setFromArray() для установки
290                 значений в новой строке</title>
292                 <programlisting language="php"><![CDATA[
293 $bugs = new Bugs();
294 $newRow = $bugs->createRow();
296 // Данные помещаются в ассоциативный массив
297 $data = array(
298     'bug_description' => '...description...',
299     'bug_status'      => 'NEW'
302 // Одновременная установка значений всех столбцов
303 $newRow->setFromArray($data);
305 // Добавление новой строки в БД
306 $newRow->save();
308                 </programlisting>
310             </example>
312         </sect3>
314         <sect3 id="zend.db.table.row.write.delete">
316             <title>Удаление строки</title>
318             <para>
319                 Вы можете использовать метод <code>delete()</code> объекта
320                 строки. Этот метод удаляет из таблицы строки, соответствующие
321                 первичному ключу в объекте строки.
322             </para>
324             <example id="zend.db.table.row.write.delete.example">
326                 <title>Пример удаления строки</title>
328                 <programlisting language="php"><![CDATA[
329 $bugs = new Bugs();
330 $row = $bugs->fetchRow('bug_id = 1');
332 // Удаление строки
333 $row->delete();
335                 </programlisting>
337             </example>
339             <para>
340                 Не нужно вызывать метод <code>save()</code> для фиксации
341                 удаления, оно сразу выполняется в БД.
342             </para>
344         </sect3>
346     </sect2>
348     <sect2 id="zend.db.table.row.serialize">
350         <title>Сериализация и десериализация строк</title>
352         <para>
353             Часто бывает удобным сохранять содержимое строки БД для последующего
354             использования. <emphasis>Сериализацией</emphasis> называется
355             действие по преобразованию объекта в форму, удобную для хранения в
356             автономном хранилище (например, в файле). Объекты типа
357             Zend_Db_Table_Row_Abstract доступны для сериализации.
358         </para>
360         <sect3 id="zend.db.table.row.serialize.serializing">
362             <title>Сериализация объекта строки</title>
364             <para>
365                 Просто используйте функцию PHP <code>serialize()</code> для
366                 получения строки, содержащей представление объекта Row в виде
367                 последовательности байт.
368             </para>
370             <example id="zend.db.table.row.serialize.serializing.example">
372                 <title>Пример сериализации объекта строки</title>
374                 <programlisting language="php"><![CDATA[
375 $bugs = new Bugs();
376 $row = $bugs->fetchRow('bug_id = 1');
378 // Преобразование объекта в сериализованную форму
379 $serializedRow = serialize($row);
381 // Теперь вы можете записать $serializedRow в файл и т.д.
383                 </programlisting>
385             </example>
387         </sect3>
389         <sect3 id="zend.db.table.row.serialize.unserializing">
391             <title>Десериализация данных строки</title>
393             <para>
394                 Используйте функцию <code>unserialize()</code> для
395                 восстановления из строки, содержащей представление объекта в
396                 виде последовательности байт. Эта функция возвращает исходный объект.
397             </para>
399             <para>
400                 Внимание: объект строки возвращается
401                 <emphasis>без соединения</emphasis>. Вы можете читать объект Row
402                 и его свойства, но не можете изменять значения в строке или
403                 выполнять другие методы, требующие соединения с БД (например,
404                 запросы к связанным таблицам).
405             </para>
407             <example id="zend.db.table.row.serialize.unserializing.example">
409                 <title>Пример десериализации объекта строки</title>
411                 <programlisting language="php"><![CDATA[
412 $rowClone = unserialize($serializedRow);
414 // Теперь вы можете использовать свойства объекта, но только для чтения
415 echo $rowClone->bug_description;
417                 </programlisting>
419             </example>
421             <note>
423                 <title>Почему объекты строки десериализуются без соединения?</title>
425                 <para>
426                     Сериализованный объект является строкой, которая доступна
427                     для чтения всем, кто ею обладает.
428                     Это создает угрозу безопасности, которая состоит в
429                     том, что в сериализованной строке сохраняются такие
430                     параметры, как логин и пароль для соединения с БД, в
431                     незашифрованном виде.
432                     Для вас может быть нежелательным сохранять такие данные в
433                     незащищенном текстовом файле, отправлять его через e-mail
434                     или любой другой носитель, который может быть прочитан
435                     потенциальным атакующим.
436                     Тот, кто прочитает сериализованный объект, не должен иметь
437                     возможности использовать его в получении
438                     несанкционированного доступа к БД.
439                 </para>
441             </note>
443         </sect3>
445         <sect3 id="zend.db.table.row.serialize.set-table">
447             <title>Восстановление соединения для объекта строки</title>
449             <para>
450                 Вы можете восстановить соединение для строки, используя метод
451                 <code>setTable()</code>. Аргументом этого метода является объект
452                 типа Zend_Db_Table_Abstract, который создается вами. Создание
453                 объекта таблицы требует действующего соединения с БД, поэтому
454                 при переустановке таблицы объект строки получает доступ к БД.
455                 После этого можно изменять значения в объекте строки и
456                 сохранять изменения в БД.
457             </para>
459             <example id="zend.db.table.row.serialize.set-table.example">
461                 <title>Пример восстановления соединения для строки</title>
463                 <programlisting language="php"><![CDATA[
464 $rowClone = unserialize($serializedRow);
466 $bugs = new Bugs();
468 // Привязка строки к таблице с действующим соединением БД
469 $rowClone->setTable($bugs);
471 // Теперь вы можете производить изменения в строке и сохранять их
472 $rowClone->bug_status = 'FIXED';
473 $rowClone->save();
475                 </programlisting>
477             </example>
479         </sect3>
481     </sect2>
483     <sect2 id="zend.db.table.row.extending">
485         <title>Расширение класса строки</title>
487         <para>
488             Zend_Db_Table_Row является используемым по умолчанию классом,
489             который наследует от Zend_Db_Table_Row_Abstract. Вы можете
490             определить свой собственный класс для экземпляров строк путем
491             наследования от Zend_Db_Table_Row_Abstract. Для того, чтобы этот
492             класс использовался для хранения результатов запросов к таблице,
493             укажите его имя в защищенном свойстве <varname>$_rowClass</varname>
494             класса таблицы или в массиве, передаваемом в качестве аргумента
495             конструктору объекта таблицы.
496         </para>
498         <example id="zend.db.table.row.extending.example">
500             <title>Указание своего класса строки</title>
502             <programlisting language="php"><![CDATA[
503 class MyRow extends Zend_Db_Table_Row_Abstract
505     // ...кастомизация
508 // Укажите свой класс строки в качестве используемого по умолчанию
509 // во всех экземплярах класса таблицы
510 class Products extends Zend_Db_Table_Abstract
512     protected $_name = 'products';
513     protected $_rowClass = 'MyRow';
516 // Или укажите свой класс строки для использования
517 // в конкретном экземпляре класса таблицы
518 $bugs = new Bugs(array('rowClass' => 'MyRow'));
520             </programlisting>
522         </example>
524         <sect3 id="zend.db.table.row.extending.overriding">
526             <title>Инициализация строки</title>
528             <para>
529                 Если при создании объекта строки требуется выполнять код,
530                 реализующий логику приложения, то вы можете поместить этот код в
531                 метод <code>init()</code>, который вызывается после того,
532                 как были обработаны все метаданные строки. Рекомендуется
533                 использовать этот способ вместо переопределения метода
534                 <code>__construct</code>, если только не требуется изменять
535                 метаданные программным путем.
537                 <example id="zend.db.table.row.init.usage.example">
539                     <title>Пример использования метода init()</title>
541                     <programlisting language="php"><![CDATA[
542 class MyApplicationRow extends Zend_Db_Table_Row_Abstract
544     protected $_role;
546     public function init()
547     {
548         $this->_role = new MyRoleClass();
549     }
552                     </programlisting>
554                 </example>
556             </para>
558         </sect3>
560         <sect3 id="zend.db.table.row.extending.insert-update">
562             <title>Определение собственной логики для добавления, обновления и удаления в Zend_Db_Table_Row</title>
564             <para>
565                 Класс строки вызывает защищенные методы <code>_insert()</code>,
566                 <code>_update()</code> и <code>_delete()</code> до выполнения
567                 соответствующих операций <code>INSERT</code>,
568                 <code>UPDATE</code> и <code>DELETE</code>. Вы можете добавлять
569                 собственную логику в эти методы в созданном вами подклассе
570                 строки.
571             </para>
573             <para>
574                 Если нужно выполнение собственной логики в определенной
575                 таблице, и эта логика должна выполняться для каждой операции в
576                 этой таблице, то разумным решением может быть реализация
577                 собственной логики в методах <code>insert()</code>,
578                 <code>update()</code> и <code>delete()</code> вашего класса
579                 таблицы. Тем не менее, иногда может быть необходимым выполнять
580                 собственную логику в классе строки.
581             </para>
583             <para>
584                 Ниже приведены примеры случаев, в которых имеет смысл
585                 реализовать свою логику в классе строки вместо класса
586                 таблицы:
587             </para>
589             <example id="zend.db.table.row.extending.overriding-example1">
590                 <title>Пример собственной логики в классе строки</title>
592                 <para>
593                     Собственная логика может применяться не во всех случаях
594                     операций над определенной таблицей. Вы можете реализовать
595                     свою логику в классе строки и создавать экземпляр класса
596                     таблицы с указанием этого класса строки в качестве
597                     используемого. Иначе в таблице используется класс
598                     строки по умолчанию.
599                 </para>
601                 <para>
602                     Вам нужно, чтобы операции над данными в этой таблице
603                     журналировались через объект Zend_Log, но только если в
604                     конфигурации приложения включено это поведение.
605                 </para>
607                 <programlisting language="php"><![CDATA[
608 class MyLoggingRow extends Zend_Db_Table_Row_Abstract
610     protected function _insert()
611     {
612         $log = Zend_Registry::get('database_log');
613         $log->info(Zend_Debug::dump($this->_data,
614                                     "INSERT: $this->_tableClass",
615                                     false)
616                   );
617     }
620 // $loggingEnabled - свойство, используемое для примера и зависящее
621 // от конфигурации вашего приложения
622 if ($loggingEnabled) {
623     $bugs = new Bugs(array('rowClass' => 'MyLoggingRow'));
624 } else {
625     $bugs = new Bugs();
628                 </programlisting>
630             </example>
632             <example id="zend.db.table.row.extending.overriding-example2">
634                 <title>Пример класса строки, журналирующего добавляемые данные для нескольких таблиц</title>
636                 <para>
637                     Собственная логика может быть общей для нескольких таблиц.
638                     Вместо реализации одной и той же логики в каждом классе
639                     таблицы вы можете реализовать код этих действий в
640                     классе строки и использовать этот класс строки во
641                     всех ваших классах таблиц.
642                 </para>
644                 <para>
645                     В этом примере журналирующий код одинаков для всех классов
646                     таблиц.
647                 </para>
649                 <programlisting language="php"><![CDATA[
650 class MyLoggingRow extends Zend_Db_Table_Row_Abstract
652     protected function _insert()
653     {
654         $log = Zend_Registry::get('database_log');
655         $log->info(Zend_Debug::dump($this->_data,
656                                     "INSERT: $this->_tableClass",
657                                     false)
658                   );
659     }
662 class Bugs extends Zend_Db_Table_Abstract
664     protected $_name = 'bugs';
665     protected $_rowClass = 'MyLoggingRow';
668 class Products extends Zend_Db_Table_Abstract
670     protected $_name = 'products';
671     protected $_rowClass = 'MyLoggingRow';
674                 </programlisting>
676             </example>
678         </sect3>
680         <sect3 id="zend.db.table.row.extending.inflection">
681             <title>Определение инфлекции в Zend_Db_Table_Row</title>
683             <para>
684                 Некоторые разработчики предпочитают, чтобы имя класса таблицы
685                 соответствовало имени таблицы в СУРБД с применением
686                 преобразования, называемого <emphasis>инфлекцией</emphasis>.
687             </para>
689             <para>
690                 Классы Zend_Db по умолчанию не производят
691                 инфлекцию. Читайте
692                 <xref linkend="zend.db.table.extending.inflection" /> для
693                 получения информации о причинах такого решения.
694             </para>
696             <para>
697                 Если вы предпочитаете использовать инфлекцию, то должны сами
698                 реализовать преобразование, переопределив метод
699                 <code>_transformColumn()</code> в своем классе строки и
700                 использовать этот класс при произведении запросов через ваш
701                 класс таблицы.
702             </para>
704             <example id="zend.db.table.row.extending.inflection.example">
706                 <title>Пример определения инфлекционного преобразования</title>
708                 <para>
709                     Это позволяет использовать в аксессорах преобразованный
710                     вариант имени столбца. Класс строки использует метод
711                     <code>_transformColumn()</code> для преобразования имени,
712                     которое используется в качестве "родного" имени столбца в
713                     таблице БД.
714                 </para>
716                 <programlisting language="php"><![CDATA[
717 class MyInflectedRow extends Zend_Db_Table_Row_Abstract
719     protected function _transformColumn($key)
720     {
721         $nativeKey = myCustomInflector($key);
722         return $nativeKey;
723     }
726 class Bugs extends Zend_Db_Table_Abstract
728     protected $_name = 'bugs';
729     protected $_rowClass = 'MyInflectedRow';
732 $bugs = new Bugs();
733 $row = $bugs->createRow();
735 // Используются имена столбцов в формате CamelCase, преобразующая функция
736 // изменяет их представление на "родное"
737 $row->bugDescription = 'New description';
739                 </programlisting>
741             </example>
743             <para>
744                 Реализация функций для произведения инфлекционного
745                 преобразования возлагается на разработчика. Zend Framework не
746                 предоставляет для этих целей готовых функций.
747             </para>
749         </sect3>
751     </sect2>
753 </sect1>
754 <!--
755 vim:se ts=4 sw=4 et: