2

ユーザーが適切に理解できるように、子カテゴリがある場合は別の順不同リスト(インデントされたテキストなど)を作成する親子カテゴリの順不同リストを作成しようとしています。

SQL を取得しましたが、foreach では、親カテゴリの下に別の順不同リストを作成して、子カテゴリのみが親カテゴリの下に表示されるように設定する方法がわかりません。

これが私のコードです

$query_cat =    "SELECT * FROM ^categories";
$query = qa_db_query_sub($query_cat);
$catsid = qa_db_read_all_assoc($query);

echo '<UL>';
foreach ($catsid as $catid){
    echo '<LI>'. $catid['title'].' '. $catid['categoryid'].'</LI>';
}
echo '</UL>';

カテゴリのテーブル イメージ

したがって、最終結果は

  • 最初のカテゴリ
    • サブカテゴリー1
  • 2 番目のカテゴリ

編集:

@vlcekmi3 answer https://stackoverflow.com/a/13451136/1053190でコードを変更した後、この結果が得られます

ここに画像の説明を入力

親リストからサブカテゴリを除外する方法は?

4

2 に答える 2

1

複雑なクエリなどを使用できます

foreach ($catsid as $catid) {
    ...
    $subquery_cat = "SELECT * FROM ^categories WHERE parentid='".$catid['categoryid']."'";
    $query = qa_db_query_sub($subquery_cat);
    $subcatsid = qa_db_read_all_assoc($query);
    // wrap into html
    ...
}
于 2012-11-19T09:42:53.593 に答える
1

あなたの設計では、これに対する本当に簡単な解決策はありません。order_in_list最も効果的な方法は、 (そして多分)のような列を追加することdepth_in_listです。

それらはループで事前に計算されます(疑似コード):

START TRANSACTION
UPDATE t1 SET order_in_list = 0 // Restart whole loop

$ids = array(0);

while $id = array_shift($ids){
   $record = SELECT * FROM t1 WHERE id = $id // Get id details, order_in_list is important
   $children = SELECT * FROM t1 WHERE parent_id = $id // get list of all childs
   // If it's root element, start indexing from 0
   $root_order = ($record ? $record->order_in_list : 1) 
   $child_no = count($children) // How many child will be adding

   // No children, nothing to do:
   if $child_no < 1{
      continue;
   }

   append_to_array($ids, $children) // Store ids to process

   // Shift all later records, we'll be creating gap in order_in_list 1,2,3,4,5
   // To 1,2,5,6,7 to insert items on places 3,4
   UPDATE t1 SET order_in_list = (order_in_list + $child_no)
      WHERE order_in_list > $record->order_in_list

   // Okay, set IDs for direct children
   foreach( $children as $child){
       UPDATE t1 SET order_in_list = $root_order, depth_in_list = $record->depth_in_list+1
          WHERE id = $child->id
       $root_order++;
   }
}
COMMIT

このようにして、次のようなレコードが取得されます。

First category, 1, 1
Second category 3, 1
Sub category, 2, 2

シンプルなループで表示できるもの:

$last_depth = 0;
foreach( (SELECT * FROM t1 ORDER by `order_in_list`) as $row){
    if( $last_detph > $row['depth_in_list'])){
       // Close level </ul>
    } else if($last_detph < $row['depth_in_list']){
       // Opening level <ul>
    } else {
       // The same depth
    }
    $last_depth = $row['depth_in_list'];
}


データベースを変更せずに

ルート要素とすべての要素を含む 2 つの配列を作成するのがおそらく最も効果的です。

$root_elements = array();
$all_elements = array();

foreach( (SELECT * FROM t1) as $row){
    // Store details into all_elements, note that entry may have already be created when
    // processing child node
    if( isset( $all_elements[$row['id']])){
      // set details
    } else {
      $all_elements[$row['id']] = $row;
      $all_elements[$row['id']]['children'] = array(); // Array of child elements
    }

    if( $row['parent_id'] == NULL){
        $all_elements[] = $row['id'];  // Add row element
    } else {
        if( isset( $all_elements[ $row[ 'parent_id']])){
            $all_elements[ $row[ 'parent_id']]['children'][] = $row['id'];
        } else {
            // Create new record:
            $all_elements[ $row[ 'parent_id']] = array();
            $all_elements[ $row[ 'parent_id']]['children'] = array($row['id']);
        }
    }
}

そして、次のように書きます。

foreach( $root_elements as $element_id){
    write_recursive( $all_elements[ $element_id]);
}

// And display
function write_recursive( $element)
{
   echo '<ul>...';
   if( count( $element['children'])){
      foreach( $element['children'] as $child){
         write_recursive( $all_elements[ $child]);
      }
   }
   echo '</ul>';
}

そのためのクラスを作成することをお勧めします(グローバル変数を使用して置き換えるため)が、これを行うための確実な方法が必要です。とにかく、多数のレコードでこれを使用しないようにしてください (2000 ~ 5000 のメニュー エントリを超えることはありません)。少なくともキャッシュするようにしてください。

注: ソリューションは、リストを表示する際のデータベースに対するリクエストの数を最小限にすることを目的としています。

于 2012-11-19T09:45:00.947 に答える