创建包含父子菜单项的多选下拉菜单


Create a multiselect drop down with parent-child menu items

我计划在php中创建一个多选下拉框或多选复选框表单元素。但与父子菜单项的关系。

例如:所以我有三个单独的表tbl_branch、tbl_area、tbl_region和另外两个表用于映射tbl_regionatoarea和tbl_areatobranch。现在我需要一个多选或多复选框,看起来像这样:

Branch 1
 Area 1
   Region 1
   Region 2
 Area 2
   Region 3
   Region 4
   Region 7
   Region 9
 Area 5
 Area 7
   Region 8
Branch 2 
 Area 3
Branch 3
Branch 4
Branch 5
 Area 6
   Region 10
 Area 2

因此,正如您所猜测的,Branch是层次结构中最顶层,region则是最底层,即Branch

我对数组和形成复杂的sql查询非常不熟悉,因此我期待着对如何做到这一点有一些指导。如果有人能帮我做同样的事,我将不胜感激。

提前感谢

我建议您对此进行读取

http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

我建立了一个几乎相同的数据树,并使用上面文档中建议的方法使问题变得简单得多,尤其是在确定n个级别的父母和兄弟姐妹时。

简短的版本是在每个节点的"左"answers"右"分配一个数字,然后使用它可以非常有效地选择树的分段。更冗长的版本在那篇文章中,对它的解释比我所能解释的要彻底得多,并包括有用的MySQL代码。

这是您的主表的潜在大纲

treeTable (
    // ID field
    id INT UNSIGNED PK AI,
    // Fields for branching
    lft INT UNSIGNED,
    rgt INT UNSIGNED,
    // ID fields for the specific types
    leafType ENUM('Branch','Area','Region'),
    leafID INT UNSIGNED,
    leafName VARCHAR
)
UNIQUE INDEX (leafType,leafID)

如果你需要每种类型的特定数据,那么你可以为它们创建单独的表,但上面的表可以让你创建树,映射出id,并允许关系与显示名称一起存储。

当然,你可以在每个叶类型之间规范化的数据越多越好,理想情况下,它们毕竟是有效的同一类型的数据,因为它们都是地理分区

以您的数据样本为例

Branch 3
Branch 4
Branch 5
 Area 6
   Region 10
 Area 2

你可能会得到这样的表格

id  lft rgt leafType    leafID  
1   1   2   'Branch'    3   
2   3   4   'Branch'    4
3   5   12  'Branch'    5
4   6   9   'Area'      6
5   7   8   'Region'    10
6   10  11  'Area'      2

关于如何插入etc的查询可以在链接文章中找到,即(逐字引用自http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/)

LOCK TABLE nested_category WRITE;
SELECT @myLeft := lft FROM nested_category
WHERE name = '2 WAY RADIOS';
UPDATE nested_category SET rgt = rgt + 2 WHERE rgt > @myLeft;
UPDATE nested_category SET lft = lft + 2 WHERE lft > @myLeft;
INSERT INTO nested_category(name, lft, rgt) VALUES('FRS', @myLeft + 1, @myLeft + 2);
UNLOCK TABLES;

然后SELECT可以说明树(再次逐字逐句地从源代码)

SELECT CONCAT( REPEAT( ' ', (COUNT(parent.name) - 1) ), node.name) AS name
FROM nested_category AS node,
        nested_category AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
GROUP BY node.name
ORDER BY node.lft;

上面2中的字段/表名称当然没有变化,但您可以根据需要更新表/字段名称

根据我的最新评论,下面是我用于插入新行的存储过程的定义

CREATE PROCEDURE `addOptionalExtraToTree`(inParentOptionID INT,inOptionName VARCHAR(40),inLeafType VARCHAR(20))
BEGIN
    DECLARE myRight INT UNSIGNED DEFAULT 0;
    SELECT optionalExtra_tree_right-1
    INTO myRight
    FROM optionalExtras
    WHERE optionalExtraID = inParentOptionID;
    IF myRight = 0 THEN
        SELECT COALESCE(MAX(optionalExtra_tree_right),0)
        INTO myRight
        FROM optionalExtras;
    END IF;
    UPDATE optionalExtras 
    SET optionalExtra_tree_right = optionalExtra_tree_right + 2 
    WHERE optionalExtra_tree_right > myRight;
    UPDATE optionalExtras 
    SET optionalExtra_tree_left = optionalExtra_tree_left + 2 
    WHERE optionalExtra_tree_left > myRight;
    INSERT INTO optionalExtras (
        optionalExtra_name,
        optionalExtra_leaf_type,
        optionalExtra_tree_left,
        optionalExtra_tree_right
    ) VALUES (
        inOptionName,
        inLeafType,
        myRight + 1,
        myRight + 2
    );
    SELECT LAST_INSERT_ID() AS optionalExtraID;
END;

然后使用诸如以下之类的调用来调用

CALL addOptionalExtraToTree(0,'New root option','Region');
CALL addOptionalExtraToTree(4,'New child option','Area');