【问题标题】:MySQL & PHP - Creating Multiple Parent Child RelationsMySQL & PHP - 创建多个父子关系
【发布时间】:2011-01-31 16:07:41
【问题描述】:

我正在尝试使用具有层次结构的类别表构建导航系统。通常,该表将定义如下:

id (int) - Primary key
name (varchar) - Name of the Category
parentid (int) - Parent ID of this Category referenced to same table (Self Join)

但问题是我要求一个类别可以是多个父类别的子类别。就像 Has and Belongs to Many (HABTM) 关系一样。

我知道如果有两个表,类别和项目,我们使用连接表 categories_items 来列出 HABTM 关系。但在这里我没有两个表,只有表,但应该以某种方式显示 HABTM 与自身的关系。这可以使用单个表吗?如果是,如何?如果不可能,在创建附加连接表时应该遵循哪些规则(表命名、字段)?

我正在尝试使用 CakePHP 来实现这一点,如果有人可以为这个问题提供 CakePHP 解决方案,那就太棒了。即使这是不可能的,任何有关创建连接表的解决方案都值得赞赏。感谢您的宝贵时间。

-- 编辑-- 我的问题似乎有点令人困惑,所以我试图重申我正在寻找的内容。 在传统的自引用(自连接)父子关系中,每个项目只能有一个父项。我正在寻找的是模拟 HABTM 关系,即每个项目的多个父项。

Categories & Items - 要定义 HABTM,我们使用 categories_items 连接表。

如果在类别中我需要 HABTM,我应该怎么做?

【问题讨论】:

  • 你可以在一个字段中保存多个值,用逗号或一些分隔符分隔它们
  • 我在谷歌搜索时发现了这一点,n2.nabble.com/…,我尝试复制相同的内容,但 Cake 仍然没有捕捉到关联。有人知道吗?

标签: php mysql cakephp join


【解决方案1】:

您想要实现的并不是真正的蛋糕方式。您应该使用两个表,它们之间有一个连接表。 Cake 的格言是“约定优于配置”,因此您应该真正使用标准的 cake 方式。

要创建 HABTM,您需要三个表。

items
categories
categories_items

Item 和 Category 与您期望的一样。您的连接表应该只包含连接表的两个 id,如下所示,

category_id
item_id

这将允许您将一个导航项显示在多个类别中,如果您愿意的话。

更多信息可以在书中找到,http://book.cakephp.org/view/1044/hasAndBelongsToMany-HABTM

【讨论】:

  • 提醒:Ashok 没有两个表,而是一个引用自身的表。 :)
  • 这是问题中要求的“蛋糕方式”:)
  • 你误解了我的问题...我不是想在类别和项目之间创建一个 HABTM...我想在类别表中创建一个 HABTM。
【解决方案2】:

试图将 n:m 关系 (HABTM) 压缩为 1:n 关系并不是一个好的做法,如果你干净利落地这样做,你会遇到一些限制,但这是你可以做到的(通用 PHP,不是 CakePHP 特定的):

您可以在表中创建一列,以将所有父 ID 存储在逗号分隔的列表中。您可以使用...读取各个 ID。

$ids = explode(',', $idsFromColumn);

...并使用...将它们写回列中

$idsForColumn = implode(',', $ids);

数据库的实际读写分别发生在这些 sn-ps 之前/之后。


如果你想正确地做到这一点,你希望你的主表看起来像这样:

id (int) - Primary key
name (varchar) - Name of the Category

你的 n:m 关系表看起来像这样:

id (int) - child
parentid (int) - parent

你会这样查询它:

SELECT ...
FROM
    main_table AS m
    [LEFT OUTER|INNER]  JOIN
    relationship_table AS r
        ON r.id=m.id
    [LEFT OUTER|INNER] JOIN
    main_table AS n
        ON r.parentid=n.id
WHERE ...

WHERE 和您的 SELECT 正是您想要的,这将取决于您希望实现的目标。至于您想要 LEFT OUTER JOIN 还是 INNER JOIN,这取决于您是否要在 m.* 中返回在您的 relationship_table 中没有条目的类别(=没有任何父母)。如果您不熟悉加入语法,请查看this Wiki article on joins

【讨论】:

    【解决方案3】:

    这几乎正是Tree behaviour 的设计目的。该行为建立在MPTT (Modified Preorder Tree Traversal) 之上。你可以这样配置它:

    将以下字段添加到您的表中:

    `parent_id` int(10) unsigned default NULL
    `lft` int(10) unsigned default NULL
    `rght` int(10) unsigned default NULL
    

    型号:

    class Category extends AppModel
    {
        var $actsAs = array('Tree');
    }
    

    然后,您将在您的类别修改表单中构建一个 parent_id <select>,然后树行为会处理其余的事情。我想您可以手动处理类别层次结构中的类别的重新排序,但您最好使用在树行为扩展的模型中提供的moveUpmoveDown 方法。

    这里还有一个有用的Tree Helper,用于将树列表转换为视图中的有序/无序列表。

    【讨论】:

    • 嗨,但即使是树行为也不能处理多个父子 HABTM 关系。在您提供的链接book.cakephp.org/view/91/Tree 中,您可以看到每个类别只能是子类别一次。换句话说,每个类别只能有一个父类别。我正在寻找的是每个类别的多个父母......
    【解决方案4】:

    我希望第二次回答还不错,因为第一次误解了这个问题。以下基本上是 pinkgothic 的答案的 CakePHP 实现。

    新的 HABTM 连接表:

    CREATE TABLE `categories_parent_categories` (
      `category_id` int(10) unsigned NOT NULL,
      `parent_category_id` int(10) unsigned default NULL,
      `order` int(10) unsigned NOT NULL default '0'
    );
    

    模型中的关联:

    class Category extends AppModel
    {
        var $hasAndBelongsToMany = array(
            'ParentCategory' => array(
                'className'             => 'Category',
                'joinTable'             => 'categories_parent_categories',
                'foreignKey'            => 'category_id',
                'associationForeignKey' => 'parent_category_id',
                'order'                 => 'CategoriesParentCategory.order'
            )
        );
    }
    

    【讨论】:

    • 您好,感谢您尝试帮助我,但恐怕代码不起作用.. Cake 没有发现关联。添加项目时,它没有显示选择父 ID 的选项..
    • 感谢 Hobonium 的输入,我能够通过对您的代码进行一些修改来获得解决方案。我把它贴在这里了。
    【解决方案5】:

    终于明白了。

    Naviitems 表:

    CREATE TABLE IF NOT EXISTS `naviitems` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `name` varchar(50) NOT NULL,
      `linkurl` varchar(250) NOT NULL,
      PRIMARY KEY (`id`)
    );
    

    自连接表:

    CREATE TABLE IF NOT EXISTS `naviitems_parents` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `naviitem_id` int(11) NOT NULL,
      `parent_id` int(11) NOT NULL,
      PRIMARY KEY (`id`)
    );
    

    Naviitems 型号:

    <?php
    class Naviitem extends AppModel {
    
        var $name = 'Naviitem';
    
        //The Associations below have been created with all possible keys, those that are not needed can be removed
        var $hasAndBelongsToMany = array(
            'Parent' => array(
                'className' => 'Naviitem',
                'joinTable' => 'naviitems_parents',
                'foreignKey' => 'naviitem_id',
                'associationForeignKey' => 'parent_id',
                'unique' => true,
                'conditions' => '',
                'fields' => '',
                'order' => '',
                'limit' => '',
                'offset' => '',
                'finderQuery' => '',
                'deleteQuery' => '',
                'insertQuery' => ''
            )
        );
    }
    ?>
    

    我已经使用 Cake Bake shell 生成了控制器和视图。现在工作正常。感谢您提供的所有想法,它们对我帮助很大。

    【讨论】:

      【解决方案6】:

      您可以使用递归来构建父/子无限树。 更多信息可以在以下网址找到。 Get Unlimited parent and child tree in php

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-16
        • 2014-03-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多