1 <sect1 id="zend.db.table.relationships">
3 <title>Связи между таблицами Zend_Db_Table</title>
5 <sect2 id="zend.db.table.relationships.introduction">
7 <title>Введение</title>
10 В реляционной БД таблицы имеют связи друг с другом. Запись в таблице
11 может быть связана с одной или более записей в другой таблице с
12 использованием ограничений ссылочной целостности, определенных в
17 Класс Zend_Db_Table_Row имеет методы для запрашивания связанных
18 строк в другой таблице.
23 <sect2 id="zend.db.table.relationships.defining">
25 <title>Определение связей</title>
28 Определите классы для каждой из ваших таблиц, расширяя абстрактный
29 класс Zend_Db_Table_Abstract, как описано в <xref
30 linkend="zend.db.table.defining" />. Также смотрите описание БД, для
31 которой написан приведнный ниже код в
32 <xref linkend="zend.db.adapter.example-database" />
36 Ниже приведено определение классов для этих таблиц:
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(
60 'columns' => 'reported_by',
61 'refTableClass' => 'Accounts',
62 'refColumns' => 'account_name'
65 'columns' => 'assigned_to',
66 'refTableClass' => 'Accounts',
67 'refColumns' => 'account_name'
70 'columns' => array('verified_by'),
71 'refTableClass' => 'Accounts',
72 'refColumns' => array('account_name')
77 class BugsProducts extends Zend_Db_Table_Abstract
79 protected $_name = 'bugs_products';
81 protected $_referenceMap = array(
83 'columns' => array('bug_id'),
84 'refTableClass' => 'Bugs',
85 'refColumns' => array('bug_id')
88 'columns' => array('product_id'),
89 'refTableClass' => 'Products',
90 'refColumns' => array('product_id')
99 Если вы используете Zend_Db_Table для эмулирования каскадных
100 операций обновления и удаления, то объявите массив
101 <varname>$_dependentTables</varname> в классе для
102 родительской таблицы. Перечислите имена классов всех зависимых
103 таблиц. Используйте имена классов, а не таблиц в БД.
108 Пропустите объявление массива <varname>$_dependentTables</varname>,
109 если используете ограничения ссылочной на сервере СУРБД для
110 реализации каскадных операций. См.
111 <xref linkend="zend.db.table.relationships.cascading" /> для
112 получения более подробной информации.
117 Объявите массив <varname>$_referenceMap</varname> во всех классах
118 зависимых таблиц. Это ассоциативный массив "правил связей". Правило
119 связи определяет, какая таблица является родительской в конкретной
120 связи, и какие столбцы в зависимой таблице ссылаются на какие
121 столбцы в родительской таблице.
125 Ключом правила является строка, используемая как индекс массива
126 <varname>$_referenceMap</varname>. Этот ключ правила используется для
127 идентификации каждой связи. Выбирайте для него описательное имя.
128 Лучше всего использовать строку, которая может быть частью имени
129 метода, как вы увидите позднее.
133 В примере выше ключами правил являются:
134 <code>'Reporter'</code>,
135 <code>'Engineer'</code>,
136 <code>'Verifier'</code>, и
137 <code>'Product'</code>.
141 Значением каждого правила в массиве <varname>$_referenceMap</varname>
142 является также ассоциативный массив. Элементы этого массива описаны
149 <emphasis>columns</emphasis> =>
150 Строка или массив строк с имен(ем/ами)
151 столбцов внешних ключей в зависимой таблице.
154 Обычно это один столбец, но некоторые таблицы имеют
160 <emphasis>refTableClass</emphasis> =>
161 Имя класса родительской таблицы. Используйте имя класса, а
165 Обычно зависимые таблицы имеют одну связь со своей
166 родительской таблицей, но некоторые таблицы имеют
167 множественные связи с одной и той же родительской таблицей.
168 В базе данных, которую мы рассматриваем для примера, таблица
169 <code>bugs</code> ссылается на таблицу
170 <code>products</code>, но имеет также три связи с таблицей
171 <code>accounts</code>.
172 Помещайте каждую ссылку в отдельную запись в массиве
173 <varname>$_referenceMap</varname>.
178 <emphasis>refColumns</emphasis> =>
179 Строка или массив строк, в котором перечислены имена
180 столбцов первичного ключа в родительской таблице.
183 Обычно это один столбец, но некоторые таблицы имеют
184 составные ключи. Если ссылка использует составной ключ, то
185 порядок столбцов в элементе <code>'columns'</code> должен
186 соответствовать порядку столбцов в элементе
187 <code>'refColumns'</code>.
190 Этот элемент является опциональным. Если вы не определите
191 <code>refColumns</code>, то по умолчанию используются имена
192 столбцов, объявленных как столбцы первичных ключей
193 родительской таблицы.
198 <emphasis>onDelete</emphasis> =>
199 Правило для действия, выполняемого, когда в родительской
200 таблице удаляется строка. См.
201 <xref linkend="zend.db.table.relationships.cascading" />
202 для получения более подробной информации.
207 <emphasis>onUpdate</emphasis> =>
208 Правило для действия, выполняемого, когда изменяются
209 значения в столбцах первичного ключа родительской таблицы.
211 <xref linkend="zend.db.table.relationships.cascading" /> для
212 получения более подробной информации.
219 <sect2 id="zend.db.table.relationships.fetching.dependent">
221 <title>Извлечение зависимых строк</title>
224 Если вы имеете объект Row (строка) в результате запроса к
225 родительской таблице, то можете извлечь строки из зависимых
226 таблиц, ссылающихся на текущую строку.
227 Используйте следующий метод:
230 <programlisting language="php">
232 $row->findDependentRowset($table, [$rule]);
237 Этот метод возвращает объект Zend_Db_Table_Rowset_Abstract,
238 содержащий набор строк из зависимой таблицы <varname>$table</varname>,
239 ссылающихся на строку, представленную объектом <varname>$row</varname>.
243 Первый аргумент <varname>$table</varname> может быть строкой с именем
244 класса зависимой таблицы. Вы можете также определить зависимую
245 таблицу, используя объект класса этой таблицы.
248 <example id="zend.db.table.relationships.fetching.dependent.example">
250 <title>Извлечение зависимых строк</title>
253 Этот пример демонстрирует получение объекта строки из таблицы
254 <code>Accounts</code> и поиск ошибок в таблице
255 <code>Bugs</code>, о которых сообщил данный пользователь.
258 <programlisting language="php">
260 $accountsTable = new Accounts();
261 $accountsRowset = $accountsTable->find(1234);
262 $user1234 = $accountsRowset->current();
264 $bugsReportedByUser = $user1234->findDependentRowset('Bugs');
271 Втрой аргумент <varname>$rule</varname> является опциональным. Это строка
272 с ключом правила в массиве <varname>$_referenceMap</varname> класса
274 Если вы не определите правило, то будет использоваться первое
275 правило из массива, ссылающееся на родительскую таблицу.
276 Для того, чтобы использовать правило, отличное от первого,
277 необходимо указать ключ.
281 В примере выше ключ правила не определен, поэтому используется
282 первое правило, соответствующее родительской таблице. Это будет правило <code>'Reporter'</code>.
285 <example id="zend.db.table.relationships.fetching.dependent.example-by">
287 <title>Извлечение зависимых строк по определенному правилу</title>
290 Этот пример демонстрирует получение строки из таблицы
291 <code>Accounts</code> и поиск ошибок в таблице
292 <code>Bugs</code>, устранение которых назначено данному
293 пользователю. Ключ правила, соответствующий этой связи в данном
294 примере - <code>'Engineer'</code>.
297 <programlisting language="php"><![CDATA[
298 $accountsTable = new Accounts();
299 $accountsRowset = $accountsTable->find(1234);
300 $user1234 = $accountsRowset->current();
302 $bugsAssignedToUser = $user1234->findDependentRowset('Bugs', 'Engineer');
310 <example id="zend.db.table.relationships.fetching.dependent.example-by-select">
312 <title>Извлечение зависимых строк с использованием Zend_Db_Table_Select</title>
315 Этот пример демонстрирует получение объекта строки из
316 таблицы <code>Accounts</code> и поиск ошибок в таблице
317 <code>Bugs</code>, устранение которых назначено данному
318 пользователю. При этом извлекается не более 3-х строк и они
319 должны быть отсортированы по имени.
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')
329 $bugsAssignedToUser = $user1234->findDependentRowset('Bugs',
337 Вы можете также запрашивать строки из зависимой таблицы, используя
338 специальный механизм -так называемые "магические методы".
339 Zend_Db_Table_Row_Abstract вызывает метод:
340 <code>findDependentRowset('<TableClass>', '<Rule>')</code>,
341 если вы вызываете метод объекта строки,
342 соответствующий одному из следующих шаблонов:
348 <varname>$row->find<TableClass>()</varname>
353 <varname>$row->find<TableClass>By<Rule>()</varname>
359 В этих шаблонах <code><TableClass></code> и
360 <code><Rule></code> являются именем класса зависимой таблицы
361 и ключом правила зависимой таблицы, ссылающегося на родительскую
368 Некоторые фреймворки приложений, такие, как Ruby on Rails,
369 используют механизм, называемый "инфлексией" (inflection), и
370 состоящий в изменении написания идентификаторов в зависимости от
371 использования. Для простоты Zend_Db_Table_Row не предоставляет
372 никакого механизма инфлексии. Имя таблицы и ключ правила в
373 вызовах методов должны в точности соответствовать написанию
374 имени класса таблицы и ключа правила при объявлении.
379 <example id="zend.db.table.relationships.fetching.dependent.example-magic">
381 <title>Извлечение зависимых строк с использованием магического
385 Этот пример демонстрирует поиск зависимых строк, эквивалентный
386 тому, что был в предыдущих примерах. В данном случае приложение
387 использует вызов магического метода вместо передачи имени
388 таблицы и ключа правила в качестве аргументов.
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();
408 <sect2 id="zend.db.table.relationships.fetching.parent">
410 <title>Извлечение родительской строки</title>
413 Если вы имеете объект Row в результате запроса к зависимой таблице,
414 то можете извлечь ту строку из родительской таблицы, на которую
415 ссылается зависимая строка.
419 <programlisting language="php"><![CDATA[
420 $row->findParentRow($table, [$rule]);
425 Зависимая строка всегда должна ссылаться только на одну строку в
426 родительской таблице, поэтому этот метод возвращает объект Row, а не
431 Первый аргумент <varname>$table</varname> может быть строкой с именем
432 класса родительской таблицы. Вы можете также задавать родительскую
433 таблицу, используя объект класса этой таблицы.
436 <example id="zend.db.table.relationships.fetching.parent.example">
438 <title>Извлечение родительской строки</title>
441 Этот пример демонстрирует получение объекта Row из таблицы
442 <code>Bugs</code> (для примера, одна из этих ошибок имеет статус
443 'NEW') и поиск строки в таблице <code>Accounts</code>,
444 соответствующей пользователю, сообщившем об этой ошибке.
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');
459 Второй аргумент <varname>$rule</varname> является опциональным. Это строка
460 с ключом правила в массиве <varname>$_referenceMap</varname> класса
462 Если вы не определите правило, то будет использоваться первое
463 правило в массиве, ссылающееся на родительскую таблицу.
464 Для того, чтобы использовать правило, отличное от первого,
465 необходимо указать ключ.
469 В примере кода выше ключ правила не определен, поэтому используется
470 первое правило, соответствующее родительской таблице. Это будет
471 правило <code>'Reporter'</code>.
474 <example id="zend.db.table.relationships.fetching.parent.example-by">
476 <title>Извлечение родительской строки по определенному правилу</title>
479 Этот пример демонстрирует получение объекта Row из таблицы
480 <code>Bugs</code> и поиск аккаунта пользователя, которому
481 назначено исправление этой ошибки. Ключ правила,
482 соответствующего этой связи в данном примере -
483 <code>'Engineer'</code>.
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');
498 Вы можете также запрашивать строки из родительской таблицы,
499 используя "магический метод".
500 Zend_Db_Table_Row_Abstract вызывает метод:
501 <code>findParentRow('<TableClass>', '<Rule>')</code>,
502 если вы вызываете метод объекта Row, соответствующий одному из
509 <varname>$row->findParent<TableClass>([Zend_Db_Table_Select $select])</varname>
515 <varname>$row->findParent<TableClass>By<Rule>([Zend_Db_Table_Select
522 В этих шаблонах <code><TableClass></code> и
523 <code><Rule></code> - соответственно имя класса родительской
524 таблицы и ключ правила зависимой таблицы, ссылающегося на
525 родительскую таблицу.
531 Имя таблицы и ключ правила в вызовах методов должны в точности
532 соответствовать написанию имени класса таблицы и ключа правила
538 <example id="zend.db.table.relationships.fetching.parent.example-magic">
540 <title>Извлечение родительской строки с использованием магического метода</title>
543 Этот пример демонстрирует поиск родительской строки,
544 эквивалентный тому, что был в предыдущих примерах. В данном
545 случае используется вызов магического метода вместо передачи
546 имени таблицы и ключа правила в качестве аргументов.
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();
566 <sect2 id="zend.db.table.relationships.fetching.many-to-many">
568 <title>Извлечение строк через связи "многие-ко-многим"</title>
571 Если вы имеете объект Row в результате выполнения запроса к одной из
572 таблиц, находящихся в связи "многие-ко-многим" (в рамках данного
573 примера будем называть эту таблицу "исходной"), вы можете извлечь
574 соответствующие строки в другой таблице ("целевая" таблица) через
575 таблицу пересечений. Используйте метод:
578 <programlisting language="php">
580 $row->findManyToManyRowset($table,
584 [Zend_Db_Table_Select $select]
591 Этот метод возвращает объект Zend_Db_Table_Rowset_Abstract,
592 содержащий строки из таблицы <varname>$table</varname>, соответствующие
593 связи "многие-ко-многим". Текущий объект строки <varname>$row</varname>
594 исходной таблицы используется в поиске строк в таблице пересечений
595 и производится объединение с целевой таблицей.
599 Первый аргумент <varname>$table</varname> может быть именем класса целевой
600 таблицы в связи "многие-ко-многим". Вы можете также задавать целевую
601 таблицу, используя объект класса этой таблицы.
605 Второй аргумент <varname>$intersectionTable</varname> может быть именем
606 класса таблицы пересечений между двумя таблицами в связи
607 "многие-ко-многим". Вы можете также задавать таблицу пересечений,
608 используя объект класса этой таблицы.
611 <example id="zend.db.table.relationships.fetching.many-to-many.example">
613 <title>Извлечение строк через метод для связей "многие-ко-многим"</title>
616 Этот пример демонстрирует получение объекта Row из исходной
617 таблицы <code>Accounts</code> и поиск строк в целевой таблице
618 <code>Products</code>, соответствующих продуктам, об ошибках в
619 которых сообщил этот пользователь.
622 <programlisting language="php"><![CDATA[
623 $bugsTable = new Bugs();
624 $bugsRowset = $bugsTable->find(1234);
625 $bug1234 = $bugsRowset->current();
627 $productsRowset = $bug1234->findManyToManyRowset('Products',
635 Третий и четвертый аргументы - <varname>$rule1</varname> и
636 <varname>$rule2</varname> - являются опциональными. Это строки с ключами
637 правил в массиве <varname>$_referenceMap</varname> класса таблицы
642 <varname>$rule1</varname> должен содержать ключ правила для ссылок таблицы
643 пересечений на исходную таблицу. В данном примере это связь между
644 таблицами <code>BugsProducts</code> и <code>Bugs</code>.
648 <varname>$rule2</varname> должен содержать ключ правила для ссылок таблицы
649 пересечений на целевую таблицу. В данном примере это связь между
650 таблицами <code>Bugs</code> и <code>Products</code>
654 Как и в случае использования методов для извлечения родительских и
655 зависимых строк, если вы не зададите правило, то метод использует
656 первое правило в массиве <varname>$_referenceMap</varname>,
657 соответствующее таблицам в связи. Если нужно использовать другое
658 правило, то необходимо указать ключ.
662 В примере кода выше ключ правила не указан, поэтому по умолчанию
663 используются первые подходящие правила из массива. В данном случае
664 для правила <varname>$rule1</varname> будет использоваться
665 <code>'Reporter'</code>, для правила <varname>$rule2</varname> -
666 <code>'Product'</code>.
669 <example id="zend.db.table.relationships.fetching.many-to-many.example-by">
671 <title>Извлечение строк через метод для связей "многие-ко-многим" по определенному правилу</title>
674 Этот пример демонстрирует получение объекта Row из исходной
675 таблицы <code>Bugs</code> и поиск строк в целевой таблице,
676 <code>Products</code>, соответствующих продуктам, к
677 которым относится данная ошибка.
680 <programlisting language="php">
682 $bugsTable = new Bugs();
683 $bugsRowset = $bugsTable->find(1234);
684 $bug1234 = $bugsRowset->current();
686 $productsRowset = $bug1234->findManyToManyRowset('Products',
695 Вы можете также запрашивать строки из целевой таблицы в связи
696 "многие-ко-многим", используя "магический метод".
697 Zend_Db_Table_Row_Abstract вызывает метод
698 <code>findManyToManyRowset('<TableClass>', '<IntersectionTableClass>', '<Rule1>', '<Rule2>')</code>, если вы вызываете метод, соотвествующий
699 одному из следующих шаблонов:
705 <varname>$row->find<TableClass>Via<IntersectionTableClass>
706 ([Zend_Db_Table_Select $select])</varname>
712 <varname>$row->find<TableClass>Via<IntersectionTableClass>By<Rule1>
713 ([Zend_Db_Table_Select $select])</varname>
719 <varname>$row->find<TableClass>Via<IntersectionTableClass>By<Rule1>And<Rule2>
720 ([Zend_Db_Table_Select $select])</varname>
726 В этих шаблонах <code><TableClass></code> и
727 <code><IntersectionTableClass></code> являются именами классов
728 целевой таблицы и таблицы пересечений
729 соответственно. <code><Rule1></code> и
730 <code><Rule2></code> являются ключами правил в таблице
731 пересечений, соответствующими исходной таблице и целевой таблице,
737 Имя таблицы и ключ правила в вызовах методов должны в точности
738 соответствовать написанию имени класса таблицы и ключа правила
743 <example id="zend.db.table.relationships.fetching.many-to-many.example-magic">
745 <title>Извлечение строк с использованием магического метода для связей "многие-ко-многим"</title>
748 Этот пример демонстрирует поиск в целевой таблице в связи
749 "многие-ко многим" строк, соответствующих продуктам, к которым
750 относится данная ошибка.
753 <programlisting language="php">
755 $bugsTable = new Bugs();
756 $bugsRowset = $bugsTable->find(1234);
757 $bug1234 = $bugsRowset->current();
759 // Используется правило связи по умолчанию
760 $products = $bug1234->findProductsViaBugsProducts();
762 // Задается правило связи
763 $products = $bug1234->findProductsViaBugsProductsByBug();
771 <sect2 id="zend.db.table.relationships.cascading">
773 <title>Каскадные операции записи</title>
776 <title>Объявление DRI в БД</title>
778 Объявление каскадных операций в Zend_Db_Table предназначено
779 <emphasis>только</emphasis> для тех СУРБД, которые
780 не поддерживают декларативной ссылочной целостности (declarative
781 referential integrity - сокр. DRI).
784 Например, если вы используете механизм хранения MyISAM в MySQL
785 или SQLite, не поддерживающие DRI, то для вас может быть
786 полезным объявить каскадные операции через Zend_Db_Table.
789 Если ваша СУРБД реализует DRI и поддерживает предложения
790 <code>ON DELETE</code> и <code>ON UPDATE</code>, то вам следует
791 объявить эти предложения в вашей БД вместо использования
792 каскадных возможностей Zend_Db_Table.
793 Объявление каскадных правил DRI в СУРБД лучше в плане
794 производительности, стабильности работы с БД и целостности
798 Тем более, не объявляйте каскадные операции
799 одновременно в СУРБД и в классе Zend_Db_Table.
804 Вы можете объявить каскадные операции для их выполнения в зависимой
805 таблице при применении операций <code>UPDATE</code> и
806 <code>DELETE</code> к строкам в родительской таблице.
809 <example id="zend.db.table.relationships.cascading.example-delete">
810 <title>Пример каскадного удаления</title>
812 Этот пример демонстрирует удаление строки в таблице
813 <code>Products</code>, которая была сконфигурирована для
814 автоматического удаления зависимых строк в таблице
817 <programlisting language="php">
819 $productsTable = new Products();
820 $productsRowset = $productsTable->find(1234);
821 $product1234 = $productsRowset->current();
823 $product1234->delete();
824 // Автоматически выполняется каскадное
825 // удаление зависимых строк в таблице Bugs
831 Аналогично, если вы используете <code>UPDATE</code> для изменения
832 значения первичного ключа в родительской таблице, то при этом часто
833 требуется, чтобы значение внешнего ключа в зависимой таблице также
834 изменялось на новое, и таким образом поддерживалась ссылочная
839 Обычно нет необходимости в том, чтобы изменять значение первичного
840 ключа, которое генерируется последовательностью (sequence) или
841 другим механизмом. Но если вы используете <emphasis>естетственные
842 ключи</emphasis>, которые иногда могут изменять свое значение, то,
843 скорее всего, нужно будет использовать каскадное обновление
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 ссылающиеся на эту строку родительской таблицы.
858 <example id="zend.db.table.relationships.cascading.example-declaration">
859 <title>Пример объявления каскадных операций</title>
861 В примере ниже строки в таблице <code>Bugs</code> автоматически
862 удаляются, если строка в таблице <code>Products</code>, на
863 которую они ссылаются, удаляется. Элемент
864 <code>'onDelete'</code> записи в массиве связей установлен в
865 <code>self::CASCADE</code>.
868 В примере ниже не выполняется каскадное обновление, если
869 изменяется значение первичного ключа. Элемент
870 <code>'onUpdate'</code> записи в массиве связей установлен в
871 <code>self::RESTRICT</code>. Вы можете получить тот же самый
872 результат, используя значение <code>self::NO_ACTION</code> или
873 пропустив элемент <code>'onUpdate'</code>.
875 <programlisting language="php"><![CDATA[
876 class BugsProducts extends Zend_Db_Table_Abstract
879 protected $_referenceMap = array(
881 'columns' => array('product_id'),
882 'refTableClass' => 'Products',
883 'refColumns' => array('product_id'),
884 'onDelete' => self::CASCADE,
885 'onUpdate' => self::RESTRICT
894 <sect3 id="zend.db.table.relationships.cascading.notes">
896 <title>Примечания относительно каскадных операций</title>
899 <emphasis>Каскадные операции, вызываемые
900 Zend_Db_Table, не являются атомарными.</emphasis>
904 Это означает, что если ваша БД реализует ограничения ссылочной
905 целостности и принуждает к их использованию, то каскадное
906 обновление, выполняемое классом Zend_Db_Table, конфликтует с
907 этими ограничениями и результатом будет нарушение ссылочной
909 Вы можете использовать каскадное обновление в Zend_Db_Table
910 <emphasis>только</emphasis> если когда ваша БД не принуждает к
911 использованию ограничений ссылочной целостности.
915 Каскадное удаление меньше страдает от проблем нарушения
916 ссылочной целостности. Вы можете удалить зависимые строки в
917 неатомарном действии до удаления родительской строки, на
918 которую они ссылаются.
922 Тем не менее, неатомарность операций изменения и удаления в
923 БД приводит к тому, что есть риск того, что другой пользователь
924 БД будет видеть противоречивые данные. Например, если вы удалите
925 строку и все зависимые строки, то есть небольшая вероятность
926 того, что другой клиент может сделать запрос к БД после того,
927 как вы удалили зависимые строки, но до того, как вы удалите
928 родительскую строку. Эта клиентская программа может увидеть
929 родительскую строку без зависимых строк и решить, что это
930 задуманное состояние данных.
934 Проблема неатомарных измнений может быть частично решена
935 использованием транзакций для изолирования ваших изменений. Но
936 некоторые СУРБД не поддерживают транзакции или позволяют
937 клиентам читать "грязные" изменения в БД, которые не были еще
942 <emphasis>Каскадные операции в Zend_Db_Table вызываются только классом Zend_Db_Table</emphasis>
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, не
959 <emphasis>Не существует каскадного добавления
960 <code>INSERT</code>.</emphasis>
964 Не поддерживается каскадное добавление <code>INSERT</code>. Вы
965 должны добавить строку в родительской таблице в одной операции и
966 добавить строки в зависимой таблице в другой операции.