Сложные справочные карты в Zend_Db_Table для учета многостолбцовых ключей

Я постараюсь сделать это как можно проще, но, боюсь, этот вариант использования выходит за рамки первоначального намерения Zend_Db. Это касается набора таблиц, которые у меня есть для разметки страниц (или чего-либо еще, например, документов) в CMS.

У меня есть три таблицы:

  1. Страницы (pages)
  2. Теги (tags)
  3. TagLink (tags_link), которая представляет собой таблицу связи "многие ко многим" между страницами и тегами.

Pages - это простая таблица (я удалил несущественные столбцы из кода ниже):

CREATE TABLE `pages` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  FULLTEXT KEY `search` (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8

Теги тоже довольно просты, хотя есть самореференциальный столбец (parent_tag_id):

CREATE TABLE `tags` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `tag` varchar(255) NOT NULL,
  `parent_tag_id` int(11) NOT NULL DEFAULT '0',
  `updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `GetByParentTagId` (`parent_tag_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8

TagLink снова довольно прост:

CREATE TABLE `tags_link` (
  `tag_id` int(11) NOT NULL,
  `module_type` varchar(50) NOT NULL,
  `foreign_key` int(11) NOT NULL,
  UNIQUE KEY `Unique` (`tag_id`,`module_type`,`foreign_key`),
  KEY `Search` (`module_type`,`foreign_key`),
  KEY `AllByTagId` (`tag_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8

Усложняющим фактором является то, что TagLink может ссылаться на любую другую таблицу в базе данных, а не только на страницы. Так что, если, например, у меня есть раздел загрузки документов, его тоже можно пометить. Чтобы облегчить этот способ работы, существует ключ с несколькими столбцами.

Чтобы прояснить это, я продемонстрирую пару запросов на вставку, которые могут выполняться при добавлении тегов в таблицу (например, Pages):

INSERT INTO `tags_link`
SET `tag_id` = '1',
    `module_type` = 'Pages',
    `foreign_key` = '2'

INSERT INTO `tags_link`
SET `tag_id` = '1',
    `module_type` = 'Documents',
    `foreign_key` = '3'

Как видите, столбец module_type - это просто произвольная строка, описывающая, где находится внешний ключ. Это не имя таблицы, поскольку все, что имеет идентификатор, может иметь теги, связанные с ним, даже если это не обязательно в базе данных MySQL.

Теперь к Zend_Db_Table $_referenceMap в PageTable:

protected $_referenceMap = array(
        'TagLink' => array(
            'columns' => 'id',
            'refTableClass' => 'Models_Tag_TagLinkTable',
            'refColumns' => 'foreign_key'
        ),
    );

Но это не учитывает мой произвольный столбец module_type и вернет любую TagLink с тем же внешним ключом. Очевидно, это плохо, потому что, например, вы получаете ссылки на теги для документов, смешанные со ссылками на страницы.

Итак, мой вопрос: как я могу учесть этот дополнительный столбец при настройке этой ссылки? Цель состоит в том, чтобы избежать наличия класса TagLink для каждого module_type, как у меня сейчас.

Я бы предположил, что что-то вроде следующего может объяснить мои требования, хотя, очевидно, это не так:

protected $_referenceMap = array(
        'TagLink' => array(
            'columns' => 'id',
            'refTableClass' => 'Models_Tag_TagLinkTable',
            'refColumns' => 'foreign_key',
            'where' => 'module_type = "Pages"'
        ),
    );

Моя текущая реализация переопределяет метод _fetch в Documents_TagLinkTable следующим образом:

protected function _fetch(Zend_Db_Table_Select $select) {
    $select->where("module_type = 'Documents_Secondary_Tags' OR module_type = 'Documents_Primary_Tags' OR module_type = 'Documents'");
    return parent::_fetch($select);
}

Как видите, к любому объекту может быть добавлено более одного набора тегов.


person Treffynnon    schedule 11.05.2011    source источник


Ответы (1)


Пример 3 в разделе «Получение зависимых наборов строк» ​​в справочнике Zend Framework демонстрирует метод, который вы можете использовать:

http://framework.zend.com/manual/en/zend.db.table.relationships.html

Хотя он не показывает предложение «where», включенное в выборку, он должен работать.

Дункан

person Duncan_m    schedule 11.05.2011
comment
аналогичный вопрос с почти таким же ответом, что и мой ... но с лучшими примерами кода: stackoverflow.com/questions/1454705/ (и от Билла Карвина, так надежно) - person Duncan_m; 11.05.2011
comment
Это именно то, чем я закончил. Это не совсем то, что я хотел, но сработает. - person Treffynnon; 11.05.2011