Zend_Db_Table中的复杂参考映射,用于计算多列密钥

时间:2011-05-11 10:22:14

标签: php zend-framework zend-db zend-db-table

我将尝试尽可能简单地保持这一点,但用例超出了Zend_Db的初衷,我担心。它涉及一组用于在CMS中标记页面(或其他任何文档)的表格。

我有三张桌子:

  1. 页面(pages
  2. 代码(tags
  3. TagLink(tags_link),这是页面和标签之间的多对多链接表
  4. 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);
    }
    

    正如您所看到的,也可能有多个标签添加到任何对象中。

1 个答案:

答案 0 :(得分:1)

Zend Framework参考中的“获取依赖行集”中的示例3演示了一种可以使用的技术:

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

虽然它没有显示select中包含的“where”子句,但它应该有效。

邓肯