Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/262.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 阵列的分层下拉菜单?_Php_Html_Arrays_Forms_Drop Down Menu - Fatal编程技术网

Php 阵列的分层下拉菜单?

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

我有下面的代码,它从我的数据库中获取字段,并将它们放置到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
        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 .= "&nbsp;&nbsp;&nbsp;";
    }

    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 .= "&nbsp;&nbsp;&nbsp;";
    }

    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>