提问人:Colm Troy 提问时间:10/1/2008 最后编辑:RahulColm Troy 更新时间:10/16/2019 访问量:2326
嵌套下拉列表
Nested dropdown
问:
我正在用php / mysql构建一个表单。我有一个表格,上面列出了位置和子位置的列表。每个子位置都有一个父位置。列“parentid”引用同一表中的另一个 locationid。我现在想按以下方式将这些值加载到下拉列表中:
--Location 1
----Sublocation 1
----Sublocation 2
----Sublocation 3
--Location 2
----Sublocation 4
----Sublocation 5
等等等等。
有没有人得到一个优雅的解决方案来做到这一点?
答:
1赞
Wayne
10/1/2008
#1
您是否正在寻找类似 OPTGROUP 标签的东西?
0赞
da5id
10/1/2008
#2
optgroup 绝对是您的不二之选。这其实就是它的用途,
例如,查看 http://www.grandhall.eu/tips/submit/ 的来源 - “Grandhall Grill Used”下的选择器。
0赞
Ross
10/1/2008
#3
您可以在实际的 HTML 中使用空格/破折号缩进。不过,您需要一个递归循环来构建它。像这样:
<?php
$data = array(
'Location 1' => array(
'Sublocation1',
'Sublocation2',
'Sublocation3' => array(
'SubSublocation1',
),
'Location2'
);
$output = '<select name="location">' . PHP_EOL;
function build_items($input, $output)
{
if(is_array($input))
{
$output .= '<optgroup>' . $key . '</optgroup>' . PHP_EOL;
foreach($input as $key => $value)
{
$output = build_items($value, $output);
}
}
else
{
$output .= '<option>' . $value . '</option>' . PHP_EOL;
}
return $output;
}
$output = build_items($data, $output);
$output .= '</select>' . PHP_EOL;
?>
或类似的东西;)
1赞
Wayne
10/1/2008
#4
注意:这只是伪代码。我没有尝试运行它,尽管您应该能够根据需要调整概念。
$parentsql = "SELECT parentid, parentname FROM table";
$result = mysql_query($parentsql);
print "<select>";
while($row = mysql_fetch_assoc($result)){
$childsql = "SELECT childID, childName from table where parentid=".$row["parentID"];
$result2 = mysql_query($childsql);
print "<optgroup label=\".$row["parentname"]."\">";
while($row2 = mysql_fetch_assoc($result)){
print "<option value=\"".$row["childID"]."\">".$row["childName"]."</option>\n";
}
print "</optgroup>";
}
print "</select>";
考虑到 BaileyP 的有效批评,以下是如何在不在每个循环中调用多个查询的开销的情况下做到这一点:
$sql = "SELECT childId, childName, parentId, parentName FROM child LEFT JOIN parent ON child.parentId = parent.parentId ORDER BY parentID, childName";
$result = mysql_query($sql);
$currentParent = "";
print "<select>";
while($row = mysql_fetch_assoc($result)){
if($currentParent != $row["parentID"]){
if($currentParent != ""){
print "</optgroup>";
}
print "<optgroup label=\".$row["parentName"]."\">";
$currentParent = $row["parentName"];
}
print "<option value=\"".$row["childID"]."\">".$row["childName"]."</option>\n";
}
print "</optgroup>"
print "</select>";
评论
0赞
Peter Bailey
10/1/2008
我对此投了反对票,因为对任何循环执行每次迭代的查询都是一个很大的禁忌。
0赞
Peter Bailey
10/1/2008
#5
理想情况下,您应该在数据库中以正确的顺序选择所有这些数据,然后循环输出。这是我对你的要求的看法
<?php
/*
Assuming data that looks like this
locations
+----+-----------+-------+
| id | parent_id | descr |
+----+-----------+-------+
| 1 | null | Foo |
| 2 | null | Bar |
| 3 | 1 | Doe |
| 4 | 2 | Rae |
| 5 | 1 | Mi |
| 6 | 2 | Fa |
+----+-----------+-------+
*/
$result = mysql_query( "SELECT id, parent_id, descr FROM locations order by coalesce(id, parent_id), descr" );
echo "<select>";
while ( $row = mysql_fetch_object( $result ) )
{
$optionName = htmlspecialchars( ( is_null( $row->parent_id ) ) ? "--{$row->descr}" : "----{$row->desc}r", ENT_COMPAT, 'UTF-8' );
echo "<option value=\"{$row->id}\">$optionName</option>";
}
echo "</select>";
如果您不喜欢使用该函数,可以向此表添加一个可以手动设置的“display_order”列,然后用于 .coalesce()
ORDER BY
评论