Связи между таблицами Zend_Db_TableВведениеВ реляционной БД таблицы имеют связи друг с другом. Запись в таблице может быть связана с одной или более записей в другой таблице с использованием ограничений ссылочной целостности, определенных в конкретной БД. Класс Zend_Db_Table_Row имеет методы для запрашивания связанных строк в другой таблице. Определение связейОпределите классы для каждой из ваших таблиц, расширяя абстрактный класс Zend_Db_Table_Abstract, как описано в Определение класса таблицы. Также смотрите описание БД, для которой написан приведнный ниже код в Пример базы данных Ниже приведено определение классов для этих таблиц:
Если вы используете Zend_Db_Table для эмулирования каскадных операций обновления и удаления, то объявите массив $_dependentTables в классе для родительской таблицы. Перечислите имена классов всех зависимых таблиц. Используйте имена классов, а не таблиц в БД.
Объявите массив $_referenceMap во всех классах зависимых таблиц. Это ассоциативный массив "правил связей". Правило связи определяет, какая таблица является родительской в конкретной связи, и какие столбцы в зависимой таблице ссылаются на какие столбцы в родительской таблице. Ключом правила является строка, используемая как индекс массива $_referenceMap. Этот ключ правила используется для идентификации каждой связи. Выбирайте для него описательное имя. Лучше всего использовать строку, которая может быть частью имени метода, как вы увидите позднее.
В примере выше ключами правил являются:
Значением каждого правила в массиве $_referenceMap является также ассоциативный массив. Элементы этого массива описаны ниже:
Извлечение зависимых строкЕсли вы имеете объект Row (строка) в результате запроса к родительской таблице, то можете извлечь строки из зависимых таблиц, ссылающихся на текущую строку. Используйте следующий метод:
Этот метод возвращает объект Zend_Db_Table_Rowset_Abstract, содержащий набор строк из зависимой таблицы $table, ссылающихся на строку, представленную объектом $row. Первый аргумент $table может быть строкой с именем класса зависимой таблицы. Вы можете также определить зависимую таблицу, используя объект класса этой таблицы. Example #1 Извлечение зависимых строк
Этот пример демонстрирует получение объекта строки из таблицы
Втрой аргумент $rule является опциональным. Это строка с ключом правила в массиве $_referenceMap класса зависимой таблицы. Если вы не определите правило, то будет использоваться первое правило из массива, ссылающееся на родительскую таблицу. Для того, чтобы использовать правило, отличное от первого, необходимо указать ключ.
В примере выше ключ правила не определен, поэтому используется
первое правило, соответствующее родительской таблице. Это будет правило Example #2 Извлечение зависимых строк по определенному правилу
Этот пример демонстрирует получение строки из таблицы
Example #3 Извлечение зависимых строк с использованием Zend_Db_Table_Select
Этот пример демонстрирует получение объекта строки из
таблицы
findDependentRowset('<TableClass>', '<Rule>') ,
если вы вызываете метод объекта строки,
соответствующий одному из следующих шаблонов:
В этих шаблонах
Example #4 Извлечение зависимых строк с использованием магического метода Этот пример демонстрирует поиск зависимых строк, эквивалентный тому, что был в предыдущих примерах. В данном случае приложение использует вызов магического метода вместо передачи имени таблицы и ключа правила в качестве аргументов.
Извлечение родительской строкиЕсли вы имеете объект Row в результате запроса к зависимой таблице, то можете извлечь ту строку из родительской таблицы, на которую ссылается зависимая строка. Используйте метод:
Зависимая строка всегда должна ссылаться только на одну строку в родительской таблице, поэтому этот метод возвращает объект Row, а не Rowset. Первый аргумент $table может быть строкой с именем класса родительской таблицы. Вы можете также задавать родительскую таблицу, используя объект класса этой таблицы. Example #5 Извлечение родительской строки
Этот пример демонстрирует получение объекта Row из таблицы
Второй аргумент $rule является опциональным. Это строка с ключом правила в массиве $_referenceMap класса зависимой таблицы. Если вы не определите правило, то будет использоваться первое правило в массиве, ссылающееся на родительскую таблицу. Для того, чтобы использовать правило, отличное от первого, необходимо указать ключ.
В примере кода выше ключ правила не определен, поэтому используется
первое правило, соответствующее родительской таблице. Это будет
правило Example #6 Извлечение родительской строки по определенному правилу
Этот пример демонстрирует получение объекта Row из таблицы
Вы можете также запрашивать строки из родительской таблицы,
используя "магический метод".
Zend_Db_Table_Row_Abstract вызывает метод:
В этих шаблонах
Example #7 Извлечение родительской строки с использованием магического метода Этот пример демонстрирует поиск родительской строки, эквивалентный тому, что был в предыдущих примерах. В данном случае используется вызов магического метода вместо передачи имени таблицы и ключа правила в качестве аргументов.
Извлечение строк через связи "многие-ко-многим"Если вы имеете объект Row в результате выполнения запроса к одной из таблиц, находящихся в связи "многие-ко-многим" (в рамках данного примера будем называть эту таблицу "исходной"), вы можете извлечь соответствующие строки в другой таблице ("целевая" таблица) через таблицу пересечений. Используйте метод:
Этот метод возвращает объект Zend_Db_Table_Rowset_Abstract, содержащий строки из таблицы $table, соответствующие связи "многие-ко-многим". Текущий объект строки $row исходной таблицы используется в поиске строк в таблице пересечений и производится объединение с целевой таблицей. Первый аргумент $table может быть именем класса целевой таблицы в связи "многие-ко-многим". Вы можете также задавать целевую таблицу, используя объект класса этой таблицы. Второй аргумент $intersectionTable может быть именем класса таблицы пересечений между двумя таблицами в связи "многие-ко-многим". Вы можете также задавать таблицу пересечений, используя объект класса этой таблицы. Example #8 Извлечение строк через метод для связей "многие-ко-многим"
Этот пример демонстрирует получение объекта Row из исходной
таблицы
Третий и четвертый аргументы - $rule1 и $rule2 - являются опциональными. Это строки с ключами правил в массиве $_referenceMap класса таблицы пересечений.
$rule1 должен содержать ключ правила для ссылок таблицы
пересечений на исходную таблицу. В данном примере это связь между
таблицами
$rule2 должен содержать ключ правила для ссылок таблицы
пересечений на целевую таблицу. В данном примере это связь между
таблицами Как и в случае использования методов для извлечения родительских и зависимых строк, если вы не зададите правило, то метод использует первое правило в массиве $_referenceMap, соответствующее таблицам в связи. Если нужно использовать другое правило, то необходимо указать ключ.
В примере кода выше ключ правила не указан, поэтому по умолчанию
используются первые подходящие правила из массива. В данном случае
для правила $rule1 будет использоваться
Example #9 Извлечение строк через метод для связей "многие-ко-многим" по определенному правилу
Этот пример демонстрирует получение объекта Row из исходной
таблицы
Вы можете также запрашивать строки из целевой таблицы в связи
"многие-ко-многим", используя "магический метод".
Zend_Db_Table_Row_Abstract вызывает метод
В этих шаблонах
Example #10 Извлечение строк с использованием магического метода для связей "многие-ко-многим" Этот пример демонстрирует поиск в целевой таблице в связи "многие-ко многим" строк, соответствующих продуктам, к которым относится данная ошибка.
Каскадные операции записи
Вы можете объявить каскадные операции для их выполнения в зависимой
таблице при применении операций Example #11 Пример каскадного удаления
Этот пример демонстрирует удаление строки в таблице
Аналогично, если вы используете Обычно нет необходимости в том, чтобы изменять значение первичного ключа, которое генерируется последовательностью (sequence) или другим механизмом. Но если вы используете естетственные ключи, которые иногда могут изменять свое значение, то, скорее всего, нужно будет использовать каскадное обновление зависимых таблиц.
Для объявления каскадных связей в Zend_Db_Table отредактируйте
правила в массиве $_referenceMap. Установите в
ассоциативного массиве под ключами Example #12 Пример объявления каскадных операций
В примере ниже строки в таблице
В примере ниже не выполняется каскадное обновление, если
изменяется значение первичного ключа. Элемент
Примечания относительно каскадных операцийКаскадные операции, вызываемые Zend_Db_Table, не являются атомарными. Это означает, что если ваша БД реализует ограничения ссылочной целостности и принуждает к их использованию, то каскадное обновление, выполняемое классом Zend_Db_Table, конфликтует с этими ограничениями и результатом будет нарушение ссылочной целостности. Вы можете использовать каскадное обновление в Zend_Db_Table только если когда ваша БД не принуждает к использованию ограничений ссылочной целостности. Каскадное удаление меньше страдает от проблем нарушения ссылочной целостности. Вы можете удалить зависимые строки в неатомарном действии до удаления родительской строки, на которую они ссылаются. Тем не менее, неатомарность операций изменения и удаления в БД приводит к тому, что есть риск того, что другой пользователь БД будет видеть противоречивые данные. Например, если вы удалите строку и все зависимые строки, то есть небольшая вероятность того, что другой клиент может сделать запрос к БД после того, как вы удалили зависимые строки, но до того, как вы удалите родительскую строку. Эта клиентская программа может увидеть родительскую строку без зависимых строк и решить, что это задуманное состояние данных. Проблема неатомарных измнений может быть частично решена использованием транзакций для изолирования ваших изменений. Но некоторые СУРБД не поддерживают транзакции или позволяют клиентам читать "грязные" изменения в БД, которые не были еще зафиксированы. Каскадные операции в Zend_Db_Table вызываются только классом Zend_Db_Table
Каскадные операции удаления и добавления, объявленные в ваших
классах Zend_Db_Table выполняются, если вы выполняете методы
Не существует каскадного добавления
Не поддерживается каскадное добавление
|