使用父子菜单项创建多选下拉列表

时间:2012-02-21 11:35:18

标签: php mysql html arrays

我打算在php中创建一个多选下拉列表或多选复选框表单元素。但是与父子菜单项关系发货。

Ex:所以我有三个单独的表tbl_branch,tbl_area,tbl_region和另外两个表用于映射tbl_regiontoarea和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

正如您猜测的那样,分支是层次结构中最顶层的,区域是最低层,即分支是父级。我希望它循环直到它找到它的孩子。一旦它停止找到任何子项,它将转移到数组中的下一个父项。

我对数组非常糟糕,并且形成了复杂的SQL查询,因此期待在如何做到这一点上有一些起步方向。如果有人能帮助我,我真的很感激。

提前致谢

1 个答案:

答案 0 :(得分:4)

我建议你给这个读一读

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

我已经建立了一个几乎相同数据的树,并使用上述文档中建议的方法使问题变得更加简单,特别是在确定父母和兄弟姐妹达到n级时。

简短版本是您在每个节点的“左”和“右”分配一个数字,然后使用它可以非常有效地选择树的片段。在这篇文章中,更长时间的卷曲版本,并且比我更彻底地解释它并且包括有用的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并允许关系与显示名称一起存储。

当然,每个leafType之间可以规范化的数据越多越好,理想情况下,它们实际上都是相同类型的数据,因为它们都是地理分段

以您的数据样本为例

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

可以在链接文章中找到有关如何插入等的查询,即(从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');