2012-01-04 28 views
-3

カテゴリとサブカテゴリを表示するには? DBに1つのテーブルがあります。カテゴリとサブカテゴリを表示するには?

CREATE TABLE IF NOT EXISTS `category` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `name` varchar(45) NOT NULL, 
    `parent_id` int(11) NOT NULL, 
    `order` int(11) NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM 

私はこのサイト上のような表示カテゴリとサブカテゴリをしたい::http://www.dealsdirect.com.au/c/baby-1/(左側のメニュー)

私の試み:付き

<?php 
include 'Category_model.php'; 
include 'Advert_model.php'; 
$nr = $_GET['id']; 

function show_category($nr){ 


    try 
     { 
      $pdo = new PDO('mysql:host=localhost;dbname=advert', 'root', ''); 
      $pdo -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 

      $stmt = $pdo -> query("SELECT * FROM category where `parent_id` = $nr"); 


      echo "<ul>"; 

      foreach ($stmt as $row){ 
       echo "<li><a href=category_view.php?id={$row['id']}> {$row['name']}</a>".show_category($row['id'])."</li>"; 

       } 
       echo "</ul>"; 
       //$id = $_GET['id']; 
       } 






     catch(PDOException $e) 
       { 
      echo 'Error!: ' . $e->getMessage(); 

      } 

    } 

    show_category($nr); 
+0

問題は何ですか? – KingCrunch

+0

どうすればいいか分かりません。 "アルゴリズム" /ステップ実行方法を教えてください – user1050014

答えて

0

この表の列は次のようになりますそのような構造では、最初に選択したアイテムのクエリを作成し、その後、選択したアイテムの親のクエリを作成する必要があります。基本的には、表示する必要があるメニューのレベルごとにクエリが必要です。

これは、ツリー関係のparent_idスキームがあまり効率的でない理由です。ネストされたセット(http://en.wikipedia.org/wiki/Nested_set_model)またはマテリアライズドパス(http://en.wikipedia.org/wiki/Materialized_pa​​th)を使用する方がはるかに優れています。アイテムの更新を行う予定がある場合は、マテリアライズされたパスはおそらく長期的に処理する方が簡単でしょう。

+0

全く真実ではありません。すべての行を選択できます。理想的にはIDでインデックス付けし、トラバースして結果を構築します。 –

+0

これは、すべての結果を必要としないため、リソースの無駄です。細部を必要としない、サブカテゴリのアイテムがたくさんある可能性があります。それとは別に、適切な構造を持っていれば、PHPで結果をトラバースして構築するのがデータベースで行うよりも遅くなります。 – Fake51

1

以下のコードを参考にしてください。これは「再帰関数」です。それは、それ自身を呼び出す関数です。 @ Fake51はちょうど言及したように、あまり効率的ではありませんが、うまくいくはずです。

作成したリストを構造化するには、いくつかのCSSが必要です。

function showItems($parent = 0) { 
    $q = "SELECT id, name FROM category WHERE parent_id = $parent"; 
    $q = mysql_query($q); 
    if(mysql_num_rows($q)) { 
     echo "<ul>"; 
     while($r = mysql_fetch_row($q)) { 
      echo "<li>"; 
      echo "<a href=\"page.php?id=".$r[0]."\">".htmlentities($r[1])."</a>"; 
      showItems($r[0]); 
      echo "</li>"\n; 
     } 
     echo "</ul>\n"; 
    } 
} 
showItems(); 

編集:まだ受け入れ答えがなかっますので、ここで潜在的にもう少し混乱はいえ、はるかに効率的である必要があり、単一のSQLクエリでそれをすべて行うように変更私のコードです。どのようにあなたのために行く参照してください。

//Recursive function to show menu items from a passed in array 
function showItems(&$menu, $parent = 0) { 
    if(is_array($menu[$parent]) && sizeof($menu[$parent])) { 
     echo "<ul>"; 
     foreach($menu[$parent] as $num=>$name) { 
      echo "<li>"; 
      echo "<a href=\"page.php?id=".$num."\">".htmlentities($name)."</a>"; 
      showItems($menu, $num); 
      echo "</li>\n"; 
     } 
     echo "</ul>\n"; 
    } 
} 

//Create a multi-dimensional array of ALL menu items, separated by parent 
$menu = array(); 
$q = "SELECT id, name, parent_id FROM category ORDER BY order"; 
$q = mysql_query($q); 
while($r = mysql_fetch_row($q)) { 
    $menu[$r[2]][$r[0]] = $r[1]; 
} 

//Call the function 
showItems($menu); 
+0

まずmysql_connect()で接続し、mysql_select_db()でデータベースを選択する必要があります。必要に応じて、これをPDOと連携するように変換することができます。 – SpoonNZ

+0

ありがとうございます。これは役に立ちます – user1050014

+0

これはひどいです。私は多くの場合、単一の選択を行い、すべてのカテゴリの配列を取得し、その1つの配列で作業します。また、カテゴリテーブル 'has_children'に別のフィールドを追加し、yes/noやbooleanのような値を格納すると、より効率的なアルゴリズムを使用できます –

-1

あなただけのカテゴリを必要とし、そのすべてのサブカテゴリを使用して、メニューの建設のための再帰を必要としない、とあなたは確かにあなたのDBの呼び出しで再帰をしたくないので、表示されました。ですから、最も基本的な解決策(1つのファイル内のすべてのコード)は、次のようなものになります。

+0

サブカテゴリをクリックすると、$ nrはサブカテゴリのIDになります。そのため、可視ツリー全体ではなく、1つのローだけを取得します。 コード内のsql expoitベクタだけでなく、失敗したクォートも言及しません。 – Fake51

+0

@ Fake51よく気づいた、ありがとう。私はコード例を更新しました。おそらくこの更新されたコードでも生産品質ではないことを指摘しておきたいと思います。このコードでは、複雑な(より深い)メニュー構造があれば、この特定のケースでは再帰、特にDBクエリによる再帰は不要ですあなたの答えに提案したような 'カテゴリ' DBテーブル構造を変更するのがより良い解決策です。 – sbgoran

関連する問題