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

Php 创建包含父子菜单项的多选下拉列表,php,mysql,html,arrays,Php,Mysql,Html,Arrays,我计划在php中创建一个多选下拉列表或多选复选框表单元素。但具有父子菜单项关系 例如:我有三个单独的表tbl_branch、tbl_area、tbl_region和另外两个表用于映射tbl_region area和tbl_area ToBranch。现在我需要一个多选或多选复选框,它看起来像这样: Branch 1 Area 1 Region 1 Region 2 Area 2 Region 3 Region 4 Region 7 Region 9 Ar

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

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

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查询非常不在行,因此我希望在如何实现这一点上有一些开始方向。如果有人能帮我,我会非常感激的


提前谢谢

我建议您阅读一下

我已经建立了一个几乎相同的数据树,并且使用上面文档中建议的方法使问题变得非常简单,特别是当涉及到确定低至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,并允许将关系与显示名称一起存储

当然,每个叶型之间的标准化数据越多越好,理想情况下,它们实际上都是相同类型的数据,因为它们都是地理分区

以您的数据样本为例

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的查询可在链接文章中找到,即(逐字引用自)

然后一个SELECT可以显示树(同样是源代码中的逐字)

当然,上面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');

我建议你看看这个

我已经建立了一个几乎相同的数据树,并且使用上面文档中建议的方法使问题变得非常简单,特别是当涉及到确定低至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,并允许将关系与显示名称一起存储

当然,每个叶型之间的标准化数据越多越好,理想情况下,它们实际上都是相同类型的数据,因为它们都是地理分区

以您的数据样本为例

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的查询可在链接文章中找到,即(逐字引用自)

然后一个SELECT可以显示树(同样是源代码中的逐字)

当然,上面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');

根据我的理解,我刚刚读了n,我看到了两个问题:首先,我将数据分布在多个表中,而不是像
类别中的
表那样仅分布在一个表中。其次,我有多个父项,比如
电子产品
,所以不管它们是否有子项,它都会循环通过所有父项。首先,您可以有多个父节点。如果有一个节点的左右比例为1:4,另一个节点的左右比例为5:6,则即使第二个节点没有子节点,SELECT也会返回所有节点。第二点是,您将所有数据视为一棵树,这表明数据类型相似,因此,为了能够有效地做到这一点,可能需要对关键区域进行重组,使其正常化,将在上面添加一个建议的表布局。因此,基本上你是在要求我创建另一个表,该表具有我的分支/区域/区域的超级映射。我还不清楚如何在这个表中插入值。如果你不介意的话,请你从我的问卷中挑选数据,向我解释一下你的表格在我的数据中会是什么样子?谢谢你提供了一个详细的例子。但我怎么知道每次我的左右值是多少呢。由于我正在为应用程序构建此功能,如何为
lft
rgt
插入正确的值?你知道我的意思吗?你可以在存储过程中添加插入逻辑。我只是在我自己的表中这样做了,其中存储过程作为输入(parentID、leafType、leaftname)(我没有单独的leaftid)。如果我将parentID指定为0,它会将其作为新的根节点添加到树的末尾。根据我的理解,我刚刚读取了n,我发现了两个问题:首先,我的数据分布在多个表上,而不是像