0

データベースからフィールドをフェッチし、それらをフォーマットの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

出力は次のとおりです。

Entry Form
Twitter
Facebook
 - Entry Form
 - Page

データベースの結合テーブルは次のようになります。

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)データベースに3回アクセスするのは非効率的です。

2)子供にも子供がいる場合は効果がありません。子の子はすべて$getChildrenに入りますが、コードは第1レベルの子のみを吐き出し、残りは無視します。

デモンストレーションの目的で、6行目がある場合:

term_id       name          slug                  taxonomy     parent
6             Single        single                format       2

次に、コードはこれを行います:

Entry Form
Twitter
Facebook
 - Entry Form
 - Page

Singleは完全に無視されますが、$getChildren配列内に含まれていることに注意してください。

では、どうすればこのコードを改善できるでしょうか。

4

3 に答える 3

1

行6には値2の親がありますが、term_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> 
于 2013-01-06T19:13:13.480 に答える
0

selectでヘッダーを作成するには、次のように表示するように出力を設定する必要があります。

    <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>

これは、どの出力がラベルであり、何がオプションであるかを何らかの方法で認識する必要があることを意味します。

于 2013-01-02T20:33:07.953 に答える
0

テストしませんでしたが、最初にすべての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>';
    }
}
于 2013-01-04T13:24:38.270 に答える