MySQL& PHP - 创建多个父子关系

时间:2010-03-25 10:55:37

标签: php mysql cakephp join

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

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

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

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

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

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

分类&项目 - 要定义HABTM,我们使用categories_items连接表。

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

6 个答案:

答案 0 :(得分:3)

我希望第二次回答第一次误解这个问题是不错的形式。以下基本上是 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'
        )
    );
}

答案 1 :(得分:2)

尝试将n:m关系(HABTM)压缩为1:n的关系并不是一种好的做法,如果干净利落的话,你会遇到你不会遇到的限制,但这就是你如何做到的(通用PHP,而不是CakePHP特定的):

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

来读取各个ID
$ids = explode(',', $idsFromColumn);

...并使用...

将它们写回专栏
$idsForColumn = implode(',', $ids);

数据库的实际读写将分别在这些片段之前/之后发生。


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

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

答案 2 :(得分:1)

这几乎就是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>,树行为将处理其余部分。我想您可以手动处理类别层次结构层中的类别重新排序,但您可能最好使用扩展了Tree行为的模型中可用的moveUpmoveDown方法。

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

答案 3 :(得分:0)

你想要实现的并不是一种真正的蛋糕方法。您应该使用两个表之间的连接表。 Cake的格言是'约定优于配置'所以你应该真正使用标准的蛋糕方式。

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

items
categories
categories_items

项目和类别正如您所期望的那样。您的连接表应该只包含连接表的两个id,如下所示,

category_id
item_id

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

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

答案 4 :(得分:0)

终于明白了。

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生成了Controller和Views。现在工作正常。感谢您贡献的所有想法,他们给了我很多帮助。

答案 5 :(得分:0)

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