[MANUAL] English:
[zend.git] / documentation / manual / ru / module_specs / Zend_Db_Table-Relationships.xml
bloba58434bf25dabb4f82c169c8d0dbc3a9e7f31739
1 <sect1 id="zend.db.table.relationships">
3     <title>Связи между таблицами Zend_Db_Table</title>
5     <sect2 id="zend.db.table.relationships.introduction">
7         <title>Введение</title>
9         <para>
10             В реляционной БД таблицы имеют связи друг с другом. Запись в таблице
11             может быть связана с одной или более записей в другой таблице с
12             использованием ограничений ссылочной целостности, определенных в
13             конкретной БД.
14         </para>
16         <para>
17             Класс Zend_Db_Table_Row имеет методы для запрашивания связанных
18             строк в другой таблице.
19         </para>
21     </sect2>
23     <sect2 id="zend.db.table.relationships.defining">
25         <title>Определение связей</title>
27         <para>
28             Определите классы для каждой из ваших таблиц, расширяя абстрактный
29             класс Zend_Db_Table_Abstract, как описано в <xref
30             linkend="zend.db.table.defining" />. Также смотрите описание БД, для
31             которой написан приведнный ниже код в
32             <xref linkend="zend.db.adapter.example-database" />
33         </para>
35         <para>
36             Ниже приведено определение классов для этих таблиц:
37         </para>
39         <programlisting language="php"><![CDATA[
40 class Accounts extends Zend_Db_Table_Abstract
42     protected $_name            = 'accounts';
43     protected $_dependentTables = array('Bugs');
46 class Products extends Zend_Db_Table_Abstract
48     protected $_name            = 'products';
49     protected $_dependentTables = array('BugsProducts');
52 class Bugs extends Zend_Db_Table_Abstract
54     protected $_name            = 'bugs';
56     protected $_dependentTables = array('BugsProducts');
58     protected $_referenceMap    = array(
59         'Reporter' => array(
60             'columns'           => 'reported_by',
61             'refTableClass'     => 'Accounts',
62             'refColumns'        => 'account_name'
63         ),
64         'Engineer' => array(
65             'columns'           => 'assigned_to',
66             'refTableClass'     => 'Accounts',
67             'refColumns'        => 'account_name'
68         ),
69         'Verifier' => array(
70             'columns'           => array('verified_by'),
71             'refTableClass'     => 'Accounts',
72             'refColumns'        => array('account_name')
73         )
74     );
77 class BugsProducts extends Zend_Db_Table_Abstract
79     protected $_name = 'bugs_products';
81     protected $_referenceMap    = array(
82         'Bug' => array(
83             'columns'           => array('bug_id'),
84             'refTableClass'     => 'Bugs',
85             'refColumns'        => array('bug_id')
86         ),
87         'Product' => array(
88             'columns'           => array('product_id'),
89             'refTableClass'     => 'Products',
90             'refColumns'        => array('product_id')
91         )
92     );
95 ]]>
96         </programlisting>
98         <para>
99             Если вы используете Zend_Db_Table для эмулирования каскадных
100             операций обновления и удаления, то объявите массив
101             <varname>$_dependentTables</varname> в классе для
102             родительской таблицы. Перечислите имена классов всех зависимых
103             таблиц. Используйте имена классов, а не таблиц в БД.
104         </para>
106         <note>
107             <para>
108                 Пропустите объявление массива <varname>$_dependentTables</varname>,
109                 если используете ограничения ссылочной на сервере СУРБД для
110                 реализации каскадных операций. См.
111                 <xref linkend="zend.db.table.relationships.cascading" /> для
112                 получения более подробной информации.
113             </para>
114         </note>
116         <para>
117             Объявите массив <varname>$_referenceMap</varname> во всех классах
118             зависимых таблиц. Это ассоциативный массив "правил связей". Правило
119             связи определяет, какая таблица является родительской в конкретной
120             связи, и какие столбцы в зависимой таблице ссылаются на какие
121             столбцы в родительской таблице.
122         </para>
124         <para>
125             Ключом правила является строка, используемая как индекс массива
126             <varname>$_referenceMap</varname>. Этот ключ правила используется для
127             идентификации каждой связи. Выбирайте для него описательное имя.
128             Лучше всего использовать строку, которая может быть частью имени
129             метода, как вы увидите позднее.
130         </para>
132         <para>
133             В примере выше ключами правил являются:
134             <code>'Reporter'</code>,
135             <code>'Engineer'</code>,
136             <code>'Verifier'</code>, и
137             <code>'Product'</code>.
138         </para>
140         <para>
141             Значением каждого правила в массиве <varname>$_referenceMap</varname>
142             является также ассоциативный массив. Элементы этого массива описаны
143             ниже:
144         </para>
146         <itemizedlist>
147             <listitem>
148                 <para>
149                     <emphasis>columns</emphasis> =>
150                     Строка или массив строк с имен(ем/ами)
151                     столбцов внешних ключей в зависимой таблице.
152                 </para>
153                 <para>
154                     Обычно это один столбец, но некоторые таблицы имеют
155                     составные ключи.
156                 </para>
157             </listitem>
158             <listitem>
159                 <para>
160                     <emphasis>refTableClass</emphasis> =>
161                     Имя класса родительской таблицы. Используйте имя класса, а
162                     не таблицы в БД.
163                 </para>
164                 <para>
165                     Обычно зависимые таблицы имеют одну связь со своей
166                     родительской таблицей, но некоторые таблицы имеют
167                     множественные связи с одной и той же родительской таблицей.
168                     В базе данных, которую мы рассматриваем для примера, таблица
169                     <code>bugs</code> ссылается на таблицу
170                     <code>products</code>, но имеет также три связи с таблицей
171                     <code>accounts</code>.
172                     Помещайте каждую ссылку в отдельную запись в массиве
173                     <varname>$_referenceMap</varname>.
174                 </para>
175             </listitem>
176             <listitem>
177                 <para>
178                     <emphasis>refColumns</emphasis> =>
179                     Строка или массив строк, в котором перечислены имена
180                     столбцов первичного ключа в родительской таблице.
181                 </para>
182                 <para>
183                     Обычно это один столбец, но некоторые таблицы имеют
184                     составные ключи. Если ссылка использует составной ключ, то
185                     порядок столбцов в элементе <code>'columns'</code> должен
186                     соответствовать порядку столбцов в элементе
187                     <code>'refColumns'</code>.
188                 </para>
189                 <para>
190                     Этот элемент является опциональным. Если вы не определите
191                     <code>refColumns</code>, то по умолчанию используются имена
192                     столбцов, объявленных как столбцы первичных ключей
193                     родительской таблицы.
194                 </para>
195             </listitem>
196             <listitem>
197                 <para>
198                     <emphasis>onDelete</emphasis> =>
199                     Правило для действия, выполняемого, когда в родительской
200                     таблице удаляется строка. См.
201                     <xref linkend="zend.db.table.relationships.cascading" />
202                     для получения более подробной информации.
203                 </para>
204             </listitem>
205             <listitem>
206                 <para>
207                     <emphasis>onUpdate</emphasis> =>
208                     Правило для действия, выполняемого, когда изменяются
209                     значения в столбцах первичного ключа родительской таблицы.
210                     См.
211                     <xref linkend="zend.db.table.relationships.cascading" /> для
212                     получения более подробной информации.
213                 </para>
214             </listitem>
215         </itemizedlist>
217     </sect2>
219     <sect2 id="zend.db.table.relationships.fetching.dependent">
221         <title>Извлечение зависимых строк</title>
223         <para>
224             Если вы имеете объект Row (строка) в результате запроса к
225             родительской таблице, то можете извлечь строки из зависимых
226             таблиц, ссылающихся на текущую строку.
227             Используйте следующий метод:
228         </para>
230         <programlisting language="php">
231 <![CDATA[
232 $row->findDependentRowset($table, [$rule]);
234         </programlisting>
236         <para>
237             Этот метод возвращает объект Zend_Db_Table_Rowset_Abstract,
238             содержащий набор строк из зависимой таблицы <varname>$table</varname>,
239             ссылающихся на строку, представленную объектом <varname>$row</varname>.
240         </para>
242         <para>
243             Первый аргумент <varname>$table</varname> может быть строкой с именем
244             класса зависимой таблицы. Вы можете также определить зависимую
245             таблицу, используя объект класса этой таблицы.
246         </para>
248         <example id="zend.db.table.relationships.fetching.dependent.example">
250             <title>Извлечение зависимых строк</title>
252             <para>
253                 Этот пример демонстрирует получение объекта строки из таблицы
254                 <code>Accounts</code> и поиск ошибок в таблице
255                 <code>Bugs</code>, о которых сообщил данный пользователь.
256             </para>
258             <programlisting language="php">
259 <![CDATA[
260 $accountsTable = new Accounts();
261 $accountsRowset = $accountsTable->find(1234);
262 $user1234 = $accountsRowset->current();
264 $bugsReportedByUser = $user1234->findDependentRowset('Bugs');
266             </programlisting>
268         </example>
270         <para>
271             Втрой аргумент <varname>$rule</varname> является опциональным. Это строка
272             с ключом правила в массиве <varname>$_referenceMap</varname> класса
273             зависимой таблицы.
274             Если вы не определите правило, то будет использоваться первое
275             правило из массива, ссылающееся на родительскую таблицу.
276             Для того, чтобы использовать правило, отличное от первого,
277             необходимо указать ключ.
278         </para>
280         <para>
281             В примере выше ключ правила не определен, поэтому используется
282             первое правило, соответствующее родительской таблице. Это будет правило <code>'Reporter'</code>.
283         </para>
285         <example id="zend.db.table.relationships.fetching.dependent.example-by">
287             <title>Извлечение зависимых строк по определенному правилу</title>
289             <para>
290                 Этот пример демонстрирует получение строки из таблицы
291                 <code>Accounts</code> и поиск ошибок в таблице
292                 <code>Bugs</code>, устранение которых назначено данному
293                 пользователю. Ключ правила, соответствующий этой связи в данном
294                 примере - <code>'Engineer'</code>.
295             </para>
297             <programlisting language="php"><![CDATA[
298 $accountsTable = new Accounts();
299 $accountsRowset = $accountsTable->find(1234);
300 $user1234 = $accountsRowset->current();
302 $bugsAssignedToUser = $user1234->findDependentRowset('Bugs', 'Engineer');
304             </programlisting>
306         </example>
308         <para>
310             <example id="zend.db.table.relationships.fetching.dependent.example-by-select">
312                 <title>Извлечение зависимых строк с использованием Zend_Db_Table_Select</title>
314                 <para>
315                     Этот пример демонстрирует получение объекта строки из
316                     таблицы <code>Accounts</code> и поиск ошибок в таблице
317                     <code>Bugs</code>, устранение которых назначено данному
318                     пользователю. При этом извлекается не более 3-х строк и они
319                     должны быть отсортированы по имени.
320                 </para>
322                 <programlisting language="php"><![CDATA[
323 $accountsTable = new Accounts();
324 $accountsRowset = $accountsTable->find(1234);
325 $user1234 = $accountsRowset->current();
326 $select = $accountsTable->select()->order('name ASC')
327                                   ->limit(3);
329 $bugsAssignedToUser = $user1234->findDependentRowset('Bugs',
330                                                      'Engineer',
331                                                      $select);
333                 </programlisting>
335             </example>
337             Вы можете также запрашивать строки из зависимой таблицы, используя
338             специальный механизм -так называемые "магические методы".
339             Zend_Db_Table_Row_Abstract вызывает метод:
340             <code>findDependentRowset('&lt;TableClass&gt;', '&lt;Rule&gt;')</code>,
341             если вы вызываете метод объекта строки,
342             соответствующий одному из следующих шаблонов:
343         </para>
345         <itemizedlist>
346             <listitem>
347                 <para>
348                     <varname>$row->find&lt;TableClass&gt;()</varname>
349                 </para>
350             </listitem>
351             <listitem>
352                 <para>
353                     <varname>$row->find&lt;TableClass&gt;By&lt;Rule&gt;()</varname>
354                 </para>
355             </listitem>
356         </itemizedlist>
358         <para>
359             В этих шаблонах <code>&lt;TableClass&gt;</code> и
360             <code>&lt;Rule&gt;</code> являются именем класса зависимой таблицы
361             и ключом правила зависимой таблицы, ссылающегося на родительскую
362             таблицу.
363         </para>
365         <note>
367             <para>
368                 Некоторые фреймворки приложений, такие, как Ruby on Rails,
369                 используют механизм, называемый "инфлексией" (inflection), и
370                 состоящий в изменении написания идентификаторов в зависимости от
371                 использования. Для простоты Zend_Db_Table_Row не предоставляет
372                 никакого механизма инфлексии. Имя таблицы и ключ правила в
373                 вызовах методов должны в точности соответствовать написанию
374                 имени класса таблицы и ключа правила при объявлении.
375             </para>
377         </note>
379         <example id="zend.db.table.relationships.fetching.dependent.example-magic">
381             <title>Извлечение зависимых строк с использованием магического
382             метода</title>
384             <para>
385                 Этот пример демонстрирует поиск зависимых строк, эквивалентный
386                 тому, что был в предыдущих примерах. В данном случае приложение
387                 использует вызов магического метода вместо передачи имени
388                 таблицы и ключа правила в качестве аргументов.
389             </para>
391             <programlisting language="php"><![CDATA[
392 $accountsTable = new Accounts();
393 $accountsRowset = $accountsTable->find(1234);
394 $user1234 = $accountsRowset->current();
396 // Используется правило связи по умолчанию
397 $bugsReportedBy = $user1234->findBugs();
399 // Задается правило связи
400 $bugsAssignedTo = $user1234->findBugsByEngineer();
402             </programlisting>
404         </example>
406     </sect2>
408     <sect2 id="zend.db.table.relationships.fetching.parent">
410         <title>Извлечение родительской строки</title>
412         <para>
413             Если вы имеете объект Row в результате запроса к зависимой таблице,
414             то можете извлечь ту строку из родительской таблицы, на которую
415             ссылается зависимая строка.
416             Используйте метод:
417         </para>
419         <programlisting language="php"><![CDATA[
420 $row->findParentRow($table, [$rule]);
422         </programlisting>
424         <para>
425             Зависимая строка всегда должна ссылаться только на одну строку в
426             родительской таблице, поэтому этот метод возвращает объект Row, а не
427             Rowset.
428         </para>
430         <para>
431             Первый аргумент <varname>$table</varname> может быть строкой с именем
432             класса родительской таблицы. Вы можете также задавать родительскую
433             таблицу, используя объект класса этой таблицы.
434         </para>
436         <example id="zend.db.table.relationships.fetching.parent.example">
438             <title>Извлечение родительской строки</title>
440             <para>
441                 Этот пример демонстрирует получение объекта Row из таблицы
442                 <code>Bugs</code> (для примера, одна из этих ошибок имеет статус
443                 'NEW') и поиск строки в таблице <code>Accounts</code>,
444                 соответствующей пользователю, сообщившем об этой ошибке.
445             </para>
447             <programlisting language="php"><![CDATA[
448 $bugsTable = new Bugs();
449 $bugsRowset = $bugsTable->fetchAll(array('bug_status = ?' => 'NEW'));
450 $bug1 = $bugsRowset->current();
452 $reporter = $bug1->findParentRow('Accounts');
454             </programlisting>
456         </example>
458         <para>
459             Второй аргумент <varname>$rule</varname> является опциональным. Это строка
460             с ключом правила в массиве <varname>$_referenceMap</varname> класса
461             зависимой таблицы.
462             Если вы не определите правило, то будет использоваться первое
463             правило в массиве, ссылающееся на родительскую таблицу.
464             Для того, чтобы использовать правило, отличное от первого,
465             необходимо указать ключ.
466         </para>
468         <para>
469             В примере кода выше ключ правила не определен, поэтому используется
470             первое правило, соответствующее родительской таблице. Это будет
471             правило <code>'Reporter'</code>.
472         </para>
474         <example id="zend.db.table.relationships.fetching.parent.example-by">
476             <title>Извлечение родительской строки по определенному правилу</title>
478             <para>
479                 Этот пример демонстрирует получение объекта Row из таблицы
480                 <code>Bugs</code> и поиск аккаунта пользователя, которому
481                 назначено исправление этой ошибки. Ключ правила,
482                 соответствующего этой связи в данном примере -
483                 <code>'Engineer'</code>.
484             </para>
486             <programlisting language="php"><![CDATA[
487 $bugsTable = new Bugs();
488 $bugsRowset = $bugsTable->fetchAll(array('bug_status = ?', 'NEW'));
489 $bug1 = $bugsRowset->current();
491 $engineer = $bug1->findParentRow('Accounts', 'Engineer');
493             </programlisting>
495         </example>
497         <para>
498             Вы можете также запрашивать строки из родительской таблицы,
499             используя "магический метод".
500             Zend_Db_Table_Row_Abstract вызывает метод:
501             <code>findParentRow('&lt;TableClass&gt;', '&lt;Rule&gt;')</code>,
502             если вы вызываете метод объекта Row, соответствующий одному из
503             следующих шаблонов:
504         </para>
506         <itemizedlist>
507             <listitem>
508                 <para>
509                     <varname>$row->findParent&lt;TableClass&gt;([Zend_Db_Table_Select $select])</varname>
510                 </para>
511             </listitem>
513             <listitem>
514                 <para>
515                     <varname>$row->findParent&lt;TableClass&gt;By&lt;Rule&gt;([Zend_Db_Table_Select
516                     $select])</varname>
517                 </para>
518             </listitem>
519         </itemizedlist>
521         <para>
522             В этих шаблонах <code>&lt;TableClass&gt;</code> и
523             <code>&lt;Rule&gt;</code> - соответственно имя класса родительской
524             таблицы и ключ правила зависимой таблицы, ссылающегося на
525             родительскую таблицу.
526         </para>
528         <note>
530             <para>
531                 Имя таблицы и ключ правила в вызовах методов должны в точности
532                 соответствовать написанию имени класса таблицы и ключа правила
533                 при объявлении.
534             </para>
536         </note>
538         <example id="zend.db.table.relationships.fetching.parent.example-magic">
540             <title>Извлечение родительской строки с использованием магического метода</title>
542             <para>
543                 Этот пример демонстрирует поиск родительской строки,
544                 эквивалентный тому, что был в предыдущих примерах. В данном
545                 случае используется вызов магического метода вместо передачи
546                 имени таблицы и ключа правила в качестве аргументов.
547             </para>
549             <programlisting language="php"><![CDATA[
550 $bugsTable = new Bugs();
551 $bugsRowset = $bugsTable->fetchAll(array('bug_status = ?', 'NEW'));
552 $bug1 = $bugsRowset->current();
554 // Используется правило связи по умолчанию
555 $reporter = $bug1->findParentAccounts();
557 // Задается правило связи
558 $engineer = $bug1->findParentAccountsByEngineer();
560             </programlisting>
562         </example>
564     </sect2>
566     <sect2 id="zend.db.table.relationships.fetching.many-to-many">
568         <title>Извлечение строк через связи "многие-ко-многим"</title>
570         <para>
571             Если вы имеете объект Row в результате выполнения запроса к одной из
572             таблиц, находящихся в связи "многие-ко-многим" (в рамках данного
573             примера будем называть эту таблицу "исходной"), вы можете извлечь
574             соответствующие строки в другой таблице ("целевая" таблица) через
575             таблицу пересечений. Используйте метод:
576         </para>
578         <programlisting language="php">
579 <![CDATA[
580 $row->findManyToManyRowset($table,
581                            $intersectionTable,
582                            [$rule1,
583                                [$rule2,
584                                    [Zend_Db_Table_Select $select]
585                                ]
586                            ]);
588         </programlisting>
590         <para>
591             Этот метод возвращает объект Zend_Db_Table_Rowset_Abstract,
592             содержащий строки из таблицы <varname>$table</varname>, соответствующие
593             связи "многие-ко-многим". Текущий объект строки <varname>$row</varname>
594             исходной таблицы используется в поиске строк в таблице пересечений
595             и производится объединение с целевой таблицей.
596         </para>
598         <para>
599             Первый аргумент <varname>$table</varname> может быть именем класса целевой
600             таблицы в связи "многие-ко-многим". Вы можете также задавать целевую
601             таблицу, используя объект класса этой таблицы.
602         </para>
604         <para>
605             Второй аргумент <varname>$intersectionTable</varname> может быть именем
606             класса таблицы пересечений между двумя таблицами в связи
607             "многие-ко-многим". Вы можете также задавать таблицу пересечений,
608             используя объект класса этой таблицы.
609         </para>
611         <example id="zend.db.table.relationships.fetching.many-to-many.example">
613             <title>Извлечение строк через метод для связей "многие-ко-многим"</title>
615             <para>
616                 Этот пример демонстрирует получение объекта Row из исходной
617                 таблицы <code>Accounts</code> и поиск строк в целевой таблице
618                 <code>Products</code>, соответствующих продуктам, об ошибках в
619                 которых сообщил этот пользователь.
620             </para>
622             <programlisting language="php"><![CDATA[
623 $bugsTable = new Bugs();
624 $bugsRowset = $bugsTable->find(1234);
625 $bug1234 = $bugsRowset->current();
627 $productsRowset = $bug1234->findManyToManyRowset('Products',
628                                                  'BugsProducts');
630             </programlisting>
632         </example>
634         <para>
635             Третий и четвертый аргументы - <varname>$rule1</varname> и
636             <varname>$rule2</varname> - являются опциональными. Это строки с ключами
637             правил в массиве <varname>$_referenceMap</varname> класса таблицы
638             пересечений.
639         </para>
641         <para>
642             <varname>$rule1</varname> должен содержать ключ правила для ссылок таблицы
643             пересечений на исходную таблицу. В данном примере это связь между
644             таблицами <code>BugsProducts</code> и <code>Bugs</code>.
645         </para>
647         <para>
648             <varname>$rule2</varname> должен содержать ключ правила для ссылок таблицы
649             пересечений на целевую таблицу. В данном примере это связь между
650             таблицами <code>Bugs</code> и <code>Products</code>
651         </para>
653         <para>
654             Как и в случае использования методов для извлечения родительских и
655             зависимых строк, если вы не зададите правило, то метод использует
656             первое правило в массиве <varname>$_referenceMap</varname>,
657             соответствующее таблицам в связи. Если нужно использовать другое
658             правило, то необходимо указать ключ.
659         </para>
661         <para>
662             В примере кода выше ключ правила не указан, поэтому по умолчанию
663             используются первые подходящие правила из массива. В данном случае
664             для правила <varname>$rule1</varname> будет использоваться
665             <code>'Reporter'</code>, для правила <varname>$rule2</varname> -
666             <code>'Product'</code>.
667         </para>
669         <example id="zend.db.table.relationships.fetching.many-to-many.example-by">
671             <title>Извлечение строк через метод для связей "многие-ко-многим" по определенному правилу</title>
673             <para>
674                 Этот пример демонстрирует получение объекта Row из исходной
675                 таблицы <code>Bugs</code> и поиск строк в целевой таблице,
676                 <code>Products</code>, соответствующих продуктам, к
677                 которым относится данная ошибка.
678             </para>
680             <programlisting language="php">
681 <![CDATA[
682 $bugsTable = new Bugs();
683 $bugsRowset = $bugsTable->find(1234);
684 $bug1234 = $bugsRowset->current();
686 $productsRowset = $bug1234->findManyToManyRowset('Products',
687                                                  'BugsProducts',
688                                                  'Bug');
690             </programlisting>
692         </example>
694         <para>
695             Вы можете также запрашивать строки из целевой таблицы в связи
696             "многие-ко-многим", используя "магический метод".
697             Zend_Db_Table_Row_Abstract вызывает метод
698             <code>findManyToManyRowset('&lt;TableClass&gt;', '&lt;IntersectionTableClass&gt;', '&lt;Rule1&gt;', '&lt;Rule2&gt;')</code>, если вы вызываете метод, соотвествующий
699             одному из следующих шаблонов:
700         </para>
702         <itemizedlist>
703             <listitem>
704                 <para>
705                     <varname>$row->find&lt;TableClass&gt;Via&lt;IntersectionTableClass&gt;
706                     ([Zend_Db_Table_Select $select])</varname>
707                 </para>
708             </listitem>
710             <listitem>
711                 <para>
712                     <varname>$row->find&lt;TableClass&gt;Via&lt;IntersectionTableClass&gt;By&lt;Rule1&gt;
713                     ([Zend_Db_Table_Select $select])</varname>
714                 </para>
715             </listitem>
717             <listitem>
718                 <para>
719                     <varname>$row->find&lt;TableClass&gt;Via&lt;IntersectionTableClass&gt;By&lt;Rule1&gt;And&lt;Rule2&gt;
720                     ([Zend_Db_Table_Select $select])</varname>
721                 </para>
722             </listitem>
723         </itemizedlist>
725         <para>
726             В этих шаблонах <code>&lt;TableClass&gt;</code> и
727             <code>&lt;IntersectionTableClass&gt;</code> являются именами классов
728             целевой таблицы и таблицы пересечений
729             соответственно. <code>&lt;Rule1&gt;</code> и
730             <code>&lt;Rule2&gt;</code> являются ключами правил в таблице
731             пересечений, соответствующими исходной таблице и целевой таблице,
732             соответственно.
733         </para>
735         <note>
736             <para>
737                 Имя таблицы и ключ правила в вызовах методов должны в точности
738                 соответствовать написанию имени класса таблицы и ключа правила
739                 при объявлении.
740             </para>
741         </note>
743         <example id="zend.db.table.relationships.fetching.many-to-many.example-magic">
745             <title>Извлечение строк с использованием магического метода для связей "многие-ко-многим"</title>
747             <para>
748                 Этот пример демонстрирует поиск в целевой таблице в связи
749                 "многие-ко многим" строк, соответствующих продуктам, к которым
750                 относится данная ошибка.
751             </para>
753             <programlisting language="php">
754 <![CDATA[
755 $bugsTable = new Bugs();
756 $bugsRowset = $bugsTable->find(1234);
757 $bug1234 = $bugsRowset->current();
759 // Используется правило связи по умолчанию
760 $products = $bug1234->findProductsViaBugsProducts();
762 // Задается правило связи
763 $products = $bug1234->findProductsViaBugsProductsByBug();
765             </programlisting>
767         </example>
769     </sect2>
771     <sect2 id="zend.db.table.relationships.cascading">
773         <title>Каскадные операции записи</title>
775         <note>
776             <title>Объявление DRI в БД</title>
777             <para>
778                 Объявление каскадных операций в Zend_Db_Table предназначено
779                 <emphasis>только</emphasis> для тех СУРБД, которые
780                 не поддерживают декларативной ссылочной целостности (declarative
781                 referential integrity - сокр. DRI).
782             </para>
783             <para>
784                 Например, если вы используете механизм хранения MyISAM в MySQL
785                 или SQLite, не поддерживающие DRI, то для вас может быть
786                 полезным объявить каскадные операции через Zend_Db_Table.
787             </para>
788             <para>
789                 Если ваша СУРБД реализует DRI и поддерживает предложения
790                 <code>ON DELETE</code> и <code>ON UPDATE</code>, то вам следует
791                 объявить эти предложения в вашей БД вместо использования
792                 каскадных возможностей Zend_Db_Table.
793                 Объявление каскадных правил DRI в СУРБД лучше в плане
794                 производительности, стабильности работы с БД и целостности
795                 данных.
796             </para>
797             <para>
798                 Тем более, не объявляйте каскадные операции
799                 одновременно в СУРБД и в классе Zend_Db_Table.
800             </para>
801         </note>
803         <para>
804             Вы можете объявить каскадные операции для их выполнения в зависимой
805             таблице при применении операций <code>UPDATE</code> и
806             <code>DELETE</code> к строкам в родительской таблице.
807         </para>
809         <example id="zend.db.table.relationships.cascading.example-delete">
810             <title>Пример каскадного удаления</title>
811             <para>
812                 Этот пример демонстрирует удаление строки в таблице
813                 <code>Products</code>, которая была сконфигурирована для
814                 автоматического удаления зависимых строк в таблице
815                 <code>Bugs</code>.
816             </para>
817             <programlisting language="php">
818 <![CDATA[
819 $productsTable  = new Products();
820 $productsRowset = $productsTable->find(1234);
821 $product1234    = $productsRowset->current();
823 $product1234->delete();
824 // Автоматически выполняется каскадное
825 // удаление зависимых строк в таблице Bugs
827             </programlisting>
828         </example>
830         <para>
831             Аналогично, если вы используете <code>UPDATE</code> для изменения
832             значения первичного ключа в родительской таблице, то при этом часто
833             требуется, чтобы значение внешнего ключа в зависимой таблице также
834             изменялось на новое, и таким образом поддерживалась ссылочная
835             целостность.
836         </para>
838         <para>
839             Обычно нет необходимости в том, чтобы изменять значение первичного
840             ключа, которое генерируется последовательностью (sequence) или
841             другим механизмом. Но если вы используете <emphasis>естетственные
842             ключи</emphasis>, которые иногда могут изменять свое значение, то,
843             скорее всего, нужно будет использовать каскадное обновление
844             зависимых таблиц.
845         </para>
847         <para>
848             Для объявления каскадных связей в Zend_Db_Table отредактируйте
849             правила в массиве <varname>$_referenceMap</varname>. Установите в
850             ассоциативного массиве под ключами  <code>'onDelete'</code> и
851             <code>'onUpdate'</code> значение 'cascade' (или константу
852             <code>self::CASCADE</code>). До того, как строка будет удалена из
853             родительской таблицы или изменится значение ее первичного ключа,
854             будут удалены или обновлены любые строки в зависимой таблице,
855             ссылающиеся на эту строку родительской таблицы.
856         </para>
858         <example id="zend.db.table.relationships.cascading.example-declaration">
859             <title>Пример объявления каскадных операций</title>
860             <para>
861                 В примере ниже строки в таблице <code>Bugs</code> автоматически
862                 удаляются, если строка в таблице <code>Products</code>, на
863                 которую они ссылаются, удаляется. Элемент
864                 <code>'onDelete'</code> записи в массиве связей установлен в
865                 <code>self::CASCADE</code>.
866             </para>
867             <para>
868                 В примере ниже не выполняется каскадное обновление, если
869                 изменяется значение первичного ключа. Элемент
870                 <code>'onUpdate'</code> записи в массиве связей установлен в
871                 <code>self::RESTRICT</code>. Вы можете получить тот же самый
872                 результат, используя значение <code>self::NO_ACTION</code> или
873                 пропустив элемент <code>'onUpdate'</code>.
874             </para>
875             <programlisting language="php"><![CDATA[
876 class BugsProducts extends Zend_Db_Table_Abstract
878     ...
879     protected $_referenceMap    = array(
880         'Product' => array(
881             'columns'           => array('product_id'),
882             'refTableClass'     => 'Products',
883             'refColumns'        => array('product_id'),
884             'onDelete'          => self::CASCADE,
885             'onUpdate'          => self::RESTRICT
886         ),
887         ...
888     );
891             </programlisting>
892         </example>
894         <sect3 id="zend.db.table.relationships.cascading.notes">
896             <title>Примечания относительно каскадных операций</title>
898             <para>
899                 <emphasis>Каскадные операции, вызываемые
900                 Zend_Db_Table, не являются атомарными.</emphasis>
901             </para>
903             <para>
904                 Это означает, что если ваша БД реализует ограничения ссылочной
905                 целостности и принуждает к их использованию, то каскадное
906                 обновление, выполняемое классом Zend_Db_Table, конфликтует с
907                 этими ограничениями и результатом будет нарушение ссылочной
908                 целостности.
909                 Вы можете использовать каскадное обновление в Zend_Db_Table
910                 <emphasis>только</emphasis> если когда ваша БД не принуждает к
911                 использованию ограничений ссылочной целостности.
912             </para>
914             <para>
915                 Каскадное удаление меньше страдает от проблем нарушения
916                 ссылочной целостности. Вы можете удалить зависимые строки в
917                 неатомарном действии до удаления родительской строки, на
918                 которую они ссылаются.
919             </para>
921             <para>
922                 Тем не менее, неатомарность операций изменения и удаления в
923                 БД приводит к тому, что есть риск того, что другой пользователь
924                 БД будет видеть противоречивые данные. Например, если вы удалите
925                 строку и все зависимые строки, то есть небольшая вероятность
926                 того, что другой клиент может сделать запрос к БД после того,
927                 как вы удалили зависимые строки, но до того, как вы удалите
928                 родительскую строку. Эта клиентская программа может увидеть
929                 родительскую строку без зависимых строк и решить, что это
930                 задуманное состояние данных.
931             </para>
933             <para>
934                 Проблема неатомарных измнений может быть частично решена
935                 использованием транзакций для изолирования ваших изменений. Но
936                 некоторые СУРБД не поддерживают транзакции или позволяют
937                 клиентам читать "грязные" изменения в БД, которые не были еще
938                 зафиксированы.
939             </para>
941             <para>
942                 <emphasis>Каскадные операции в Zend_Db_Table вызываются только классом Zend_Db_Table</emphasis>
943             </para>
945             <para>
946                 Каскадные операции удаления и добавления, объявленные в ваших
947                 классах Zend_Db_Table выполняются, если вы выполняете методы
948                 <code>save()</code> и <code>delete()</code> класса Row.
949                 Но если вы обновляете или удаляете данные, используя другой
950                 интерфейс, например, утилиту запросов или другое приложение, то
951                 каскадные операции не выполняются.
952                 Даже когда используются методы <code>update()</code> и
953                 <code>delete()</code> класса Zend_Db_Adapter, каскадные
954                 операции, определенные в ваших классах Zend_Db_Table, не
955                 выполняются.
956             </para>
958             <para>
959                 <emphasis>Не существует каскадного добавления
960                 <code>INSERT</code>.</emphasis>
961             </para>
963             <para>
964                 Не поддерживается каскадное добавление <code>INSERT</code>. Вы
965                 должны добавить строку в родительской таблице в одной операции и
966                 добавить строки в зависимой таблице в другой операции.
967             </para>
969         </sect3>
971     </sect2>
973 </sect1>
974 <!--
975 vim:se ts=4 sw=4 et: