Автоматическое объединение таблиц без нарушения поведения по умолчанию в Zend Framework - PullRequest
7 голосов
/ 24 октября 2008

Ситуация следующая: у меня есть 2 модели: «Действие» и «Пользователь». Эти модели ссылаются на таблицы «действия» и «пользователи» соответственно.

Моя таблица действий содержит столбец user_id. На данный момент мне нужен обзор всех действий и пользователей, которым они назначены. Когда я использую $action->fetchAll(), у меня есть только идентификатор пользователя, поэтому я хочу иметь возможность объединить данные из пользовательской модели, желательно без вызова findDependentRowset().

Я думал о создании пользовательских методов fetchAll(), fetchRow() и find() в моей модели, но это нарушило бы поведение по умолчанию.

Как лучше всего решить эту проблему? Любая помощь будет принята с благодарностью.

Ответы [ 3 ]

14 голосов
/ 26 октября 2008

Я разработал и реализовал функцию табличных отношений в Zend Framework.

Мой первый комментарий заключается в том, что вы все равно не будете использовать findDependentRowset() - вы будете использовать findParentRow(), если в действии есть ссылка на внешний ключ для пользователя.

$actionTable = new Action();
$actionRowset = $actionTable->fetchAll();
foreach ($actionRowset as $actionRow) {
  $userRow = $actionRow->findParentRow('User');
}

Редактировать: В цикле у вас теперь есть объект $ actionRow и $ userRow. Вы можете записать изменения обратно в базу данных через любой объект, изменив поля объекта и вызвав save() для объекта.

Вы также можете использовать класс Zend_Db_Table_Select (который был реализован после того, как я покинул проект), чтобы получить набор строк на основе соединения между действием и пользователем.

$actionTable = new Action();
$actionQuery = $actionTable->select()
  ->setIntegrityCheck(false) // allows joins
  ->from($actionTable)
  ->join('user', 'user.id = action.user_id');
$joinedRowset = $actionTable->fetchAll($actionQuery);
foreach ($joinedRowset as $joinedRow) {
  print_r($joinedRow->toArray());
}

Обратите внимание, что такой набор строк, основанный на запросе соединения, доступен только для чтения. Вы не можете установить значения полей в объектах Row и вызвать save(), чтобы отправить изменения обратно в базу данных.

Редактировать: Нет способа сделать произвольный объединенный результирующий набор доступным для записи. Рассмотрим простой пример на основе приведенного выше набора результатов:

action_id  action_type  user_id  user_name
   1          Buy          1       Bill
   2          Sell         1       Bill
   3          Buy          2       Aron
   4          Sell         2       Aron

Далее для строки с action_id = 1 я изменяю одно из полей, полученных из объекта User:

$joinedRow->user_name = 'William';
$joinedRow->save();

Вопросы: когда я просматриваю следующий ряд с action_id = 2, должен ли я увидеть «Билла» или «Уильяма»? Если 'Уильям', означает ли это, что строка сохранения 1 должна автоматически обновить 'Билл' до 'Уильям' во всех других строках в этом наборе результатов? Или это означает, что save() автоматически перезапускает запрос SQL, чтобы получить обновленный набор результатов из базы данных? Что делать, если запрос занимает много времени?

Также рассмотрим объектно-ориентированный дизайн. Каждая строка является отдельным объектом. Целесообразно ли, чтобы вызов save() для одного объекта имел побочный эффект изменения значений в отдельном объекте (даже если они являются частью одной коллекции объектов)? Мне это кажется формой Content Coupling .

Приведенный выше пример является относительно простым запросом, но разрешены и более сложные запросы. Zend_Db не может анализировать запросы с целью отличить доступные для записи результаты от результатов только для чтения. Именно поэтому представления MySQL не обновляются.

2 голосов
/ 25 октября 2008

Вы всегда можете создать представление в своей базе данных, которое сделает объединение за вас.

CREATE OR REPLACE VIEW VwAction AS
SELECT [columns]
  FROM action
  LEFT JOIN user
    ON user.id = action.user_id

Тогда просто используйте

$vwAction->fetchAll();

Просто помните, что представления в MySQL доступны только для чтения (при условии, что это MySQL)

1 голос
/ 27 октября 2009

разве создание таблицы sql view не является хорошим решением для совместной работы? и после простого табличного класса для доступа к нему

Я думаю, что лучше, если ваша логика в sql, чем в php

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...