我将尝试尽可能简单地保持这一点,但用例超出了Zend_Db的初衷,我担心。它涉及一组用于在CMS中标记页面(或其他任何文档)的表格。
我有三张桌子:
pages
)tags
)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
列只是一个任意字符串,用于描述可以找到外键的位置。这不是表的名称,但是任何带有ID的东西都可以链接到它,即使它不一定在MySQL数据库中。
现在转到Zend_Db_Table
中的$_referenceMap
PageTable
:
protected $_referenceMap = array(
'TagLink' => array(
'columns' => 'id',
'refTableClass' => 'Models_Tag_TagLinkTable',
'refColumns' => 'foreign_key'
),
);
但是这并没有考虑我的任意module_type
列,并且会返回任何具有相同外键的TagLink。显然这很糟糕,因为你获得了混合文档的TagLinks和例如页面的文档。
所以我的问题是在设置此引用时如何考虑此附加列?目的是避免像我现在一样为每个module_type
建立一个TagLink类。
我会想象下面的内容可以解释我的要求,虽然显然这不是如何做到的:
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);
}
正如您所看到的,也可能有多个标签添加到任何对象中。
答案 0 :(得分:1)
Zend Framework参考中的“获取依赖行集”中的示例3演示了一种可以使用的技术:
http://framework.zend.com/manual/en/zend.db.table.relationships.html
虽然它没有显示select中包含的“where”子句,但它应该有效。
邓肯