Php 阵列的分层下拉菜单?
我有下面的代码,它从我的数据库中获取字段,并将它们放置到html表单的下拉菜单中以获取格式。在它的当前形式中,我从数据库中提取了3次,代码的注释中解释了代码的工作原理:Php 阵列的分层下拉菜单?,php,html,arrays,forms,drop-down-menu,Php,Html,Arrays,Forms,Drop Down Menu,我有下面的代码,它从我的数据库中获取字段,并将它们放置到html表单的下拉菜单中以获取格式。在它的当前形式中,我从数据库中提取了3次,代码的注释中解释了代码的工作原理: $getSolos = $wpdb->get_results($wpdb->prepare(" SELECT * FROM wp_terms p LEFT OUTER JOIN wp_term_taxonomy t ON p.term_id = t.term_id W
$getSolos = $wpdb->get_results($wpdb->prepare("
SELECT * FROM wp_terms p
LEFT OUTER JOIN wp_term_taxonomy t ON p.term_id = t.term_id
WHERE t.taxonomy = 'format'
AND t.parent = 0
AND t.term_id NOT IN (SELECT parent FROM wp_term_taxonomy WHERE taxonomy = 'format' AND parent > 0)
ORDER BY t.parent
")); // This fetches all rows that do not have children or parents.
$getParents = $wpdb->get_results($wpdb->prepare("
SELECT * FROM wp_terms p
LEFT OUTER JOIN wp_term_taxonomy t ON p.term_id = t.term_id
WHERE t.taxonomy = 'format'
AND t.parent = 0
AND t.term_id IN (SELECT parent FROM wp_term_taxonomy WHERE taxonomy = 'format' AND parent > 0)
")); // This fetches all rows that have children
$getChildren = $wpdb->get_results($wpdb->prepare("
SELECT * FROM wp_terms p
LEFT OUTER JOIN wp_term_taxonomy t ON p.term_id = t.term_id
WHERE t.taxonomy = 'format'
AND t.parent > 0
ORDER BY t.parent
AND p.name
")); //This fetches all rows that ARE children
<select name="format"> //start the dropdown
<option value="empty"></option> //default field is empty
<?php
foreach ($getSolos as $solo) { //start loop through solos for output
echo "<option value='".$solo->name."'>".$solo->name."</option>"; // output solos as options in the dropdown
}
foreach ($getParents as $parent) { //start loop through parents for output
echo "<optgroup label='".$parent->name."'>"; // Spit out parent as an optgroup
foreach ($getChildren as $child) { //Start loop through children for output
if ($child->parent == $parent->term_id) { // if child's parent value matches the ID of the parent
echo "<option value='".$child->name."'> ".$child->name."</option>"; //Spit out the child as an option
}
}
echo "</optgroup>"; //close the optgroup
}
?>
</select> // end the dropdown
数据库中的组合表如下所示:
term_id name slug taxonomy parent
1 Entry Form entry-form format 0
2 Page page format 3
3 Facebook facebook format 0
4 Entry Form facebook-entry-form format 3
5 Twitter twitter format 0
然而,这种方法存在一个问题
1) 三次访问数据库效率很低
2) 如果一个孩子也有一个孩子,这是无效的。虽然children的子级都进入$getChildren,但代码只会吐出第一级子级,而忽略其余的子级
出于演示目的,如果我有第六排:
term_id name slug taxonomy parent
6 Single single format 2
然后代码将执行以下操作:
Entry Form
Twitter
Facebook
- Entry Form
- Page
请注意,虽然Single包含在$getChildren数组中,但它被完全忽略
那么,如何改进此代码呢?您需要将输出设置为如下显示,以便在选择中创建标题:
<select>
<optgroup label="Swedish Cars">
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
</optgroup>
<optgroup label="German Cars">
<option value="mercedes">Mercedes</option>
<option value="audi">Audi</option>
</optgroup>
</select>
沃尔沃汽车
萨博
梅赛德斯
奥迪
这意味着您需要以某种方式识别哪些输出应该是标签,哪些应该是选项。没有对其进行测试,但我将首先创建一个包含所有ID的分层数组:
$items = array();
$ids = array();
foreach ($getFormats as $format) {
$items[$format->term_id] = $format;
if (isset($format->parent)) {
$ids[$format->parent->term_id][] = $format->term_id;
} else $ids[$format->term_id] = null;
}
然后很容易遍历此数组并创建HTML代码:
foreach ($ids as $id => $subIds) {
if (!empty($subIds)) {
echo '<optgroup label="' . $items[$id]->name . '">';
foreach ($subIds as $subId)
echo '<option value="' . $items[$subId]->name . '">' . $items[$subId]->name . '</option>';
echo '</optgroup>';
} else {
echo '<option value="' . $items[$id]->name . '">' . $items[$id]->name . '</option>';
}
}
foreach($id作为$id=>$subid){
如果(!空($subid)){
回声';
foreach($subId作为$subId)
回显'.$items[$subId]->name';
回声';
}否则{
回显'.$items[$id]->name';
}
}
第6行有一个值为2的父级。尽管具有项_id 2的行有一个值为3的父对象,因此不包括在父对象中
我可能会使用一个函数来实现这一点
$getTerms = $wpdb->get_results($wpdb->prepare("
SELECT * FROM wp_terms p
WHERE t.taxonomy = 'format'
ORDER BY p.name ASC"));
$terms = array();
foreach($getTerms as $key => $term){
$terms[$term->parent][$term->term_id] = $term;
}
function printTerms($terms, $parent = 0, $deep = 0){
if(count($terms[$parent]) > 0){
$indent = "";
for($i = 0; $i < $deep; $i++){
$indent .= " ";
}
foreach($terms[$parent] as $key => $term){
if(count($terms[$term->term_id]) > 0){
if($deep == 0){
echo "<optgroup label='".$term->name."'></optgroup>";
} else {
echo "<option value='".$term->name."'>".$indent.$term->name."</option>";
}
printTerms($terms, $term->term_id, ($deep+1));
} else {
echo "<option value='".$term->name."'>".$indent.$term->name."</option>";
}
}
}
}
?>
<select name="format">
<option value="empty"></option>
<?php printTerms($terms); ?>
</select>
$getTerms=$wpdb->get_结果($wpdb->prepare('
从wp_术语p中选择*
其中t.taxonomy='format'
按p.名称(ASC)订购;
$terms=array();
foreach($key=>$term的getTerms){
$terms[$term->parent][$term->term\u id]=$term;
}
函数printTerms($terms,$parent=0,$deep=0){
如果(计数($terms[$parent])>0{
$indent=“”;
对于($i=0;$i<$deep;$i++){
$indent.=“”;
}
foreach($terms[$parent]作为$key=>$term){
如果(计数($terms[$term->term\u id])>0){
如果($deep==0){
回声“;
}否则{
回显“$indent.$term->name.”;
}
printTerms($terms,$term->term_id,($deep+1));
}否则{
回显“$indent.$term->name.”;
}
}
}
}
?>
我相信这是可能的,但我需要帮助才能做到这一点。请查看我的更新问题和新信息。您需要退出foreach循环,并在while循环中获取此信息。然后你只需要做条件检查。例:如果($format->parent)执行此操作,否则执行此操作。这是一个开始,但理想情况下,optgroup只应用于顶级父级,而子父级是可选的。在这种情况下,您可以在parent=0上进行检查。当它不是0时,您可以简单地输出一个选项。我明天会更新答案,我在打电话;)我编辑了printTerms()函数。它现在支持可选择的子级别父级,optgroup不支持可选择的标签,所以我使用了缩进来可视化级别层次结构,这取决于深度;我使用了1个查询来检索我们需要的数据。让PHP为您完成这项工作吧!:)代码根本不输出任何缩进。它以optgroup的形式打印出Facebook,但它的子项没有缩进,这些子项的子项也没有缩进。我想原因是因为它呼应着“我的爱”;这会在任何内容插入到optgroup之前关闭optgroup。好吧,它会创建下拉列表,但所有内容都被视为相同的。optgroups似乎不起作用。我们可以举一个数据库源的例子吗?感觉这是可以通过一些sql技巧来完成的…示例已经提供。您给出了一个表,但在示例中使用了更多。。。耸耸肩
$getTerms = $wpdb->get_results($wpdb->prepare("
SELECT * FROM wp_terms p
WHERE t.taxonomy = 'format'
ORDER BY p.name ASC"));
$terms = array();
foreach($getTerms as $key => $term){
$terms[$term->parent][$term->term_id] = $term;
}
function printTerms($terms, $parent = 0, $deep = 0){
if(count($terms[$parent]) > 0){
$indent = "";
for($i = 0; $i < $deep; $i++){
$indent .= " ";
}
foreach($terms[$parent] as $key => $term){
if(count($terms[$term->term_id]) > 0){
if($deep == 0){
echo "<optgroup label='".$term->name."'></optgroup>";
} else {
echo "<option value='".$term->name."'>".$indent.$term->name."</option>";
}
printTerms($terms, $term->term_id, ($deep+1));
} else {
echo "<option value='".$term->name."'>".$indent.$term->name."</option>";
}
}
}
}
?>
<select name="format">
<option value="empty"></option>
<?php printTerms($terms); ?>
</select>