2011-12-08 13 views
1

私は階層検出スクリプトをコーディングしようとしていますが、私は既にスクリプトを書いていますが、4レベルしか下げることはできません。無限のレベルで動作する数行にこれを凝縮する方法はありますか?より効率的な階層システム

このスクリプトは基本的に同じコードのコピーであり、categoriesための貼り付け4回

<?php 
function listCategories($name, $disable_status = 0, $show_nums = 0) { 
    echo "<select name='".$name."'>"; 
    $result = mysql_query("SELECT * FROM categories") or die(mysql_error()); 
    while($row = mysql_fetch_array($result)) { 
     if($row['parent_id']==0) { 
      $result2 = mysql_query("SELECT * FROM categories WHERE parent_id=".$row['id']) or die(mysql_error()); 
      echo "<option value='".$row['id']."'"; 

      if($disable_status==1&&isParent($row['id'])){ 
       echo " disabled='disabled'"; 
      } 
      echo ">".$row['name']."</option>"; 

      while($row2 = mysql_fetch_array($result2)) { 
       $result3 = mysql_query("SELECT * FROM categories WHERE parent_id=".$row2['id']) or die(mysql_error()); 
       echo "<option value='".$row2['id']."'"; 
       if($disable_status==1&&isParent($row2['id'])){ 
        echo " disabled='disabled'"; 
       } 
       echo ">- ".$row2['name']."</option>"; 

       while($row3 = mysql_fetch_array($result3)) { 
        $result4 = mysql_query("SELECT * FROM categories WHERE parent_id=".$row3['id']) or die(mysql_error()); 
        echo "<option value='".$row3['id']."'"; 
        if($disable_status==1&&isParent($row3['id'])){ 
         echo " disabled='disabled'"; 
        } 
        echo ">-- ".$row3['name']."</option>"; 

        while($row4 = mysql_fetch_array($result4)) { 
         echo "<option value='".$row4['id']."'>[".$row4['id']."] --- ".$row4['name']."</option>"; 
        } 
       } 
      } 
     } 
    } 
    echo "</select>"; 
} 

function isParent($cat_ID) { 
    $result = mysql_query("SELECT * FROM categories WHERE parent_id=".$cat_ID) or die(mysql_error()); 
    if(mysql_num_rows($result)==0) { 
     return FALSE; 
    } else { 
     return TRUE; 
    } 
} 

私のテーブル構造が

id, name, parent_id

あるカテゴリに親がない場合は、parent_idになります0それ以外の場合は、親のカテゴリのidになります。

すべてのご協力をいただきありがとうございます。

+0

この問題を解決するために再帰を使用できます。私はすぐに詳細を説明する時間がありません - うまくいけば誰かがすぐになります:) – Treffynnon

+0

OMG my eyeeeeees !!! TT – CAFxX

+0

この回答はあなたにとって単純すぎるかもしれません。http://stackoverflow.com/questions/5291054/hierarchical-sql-problem/5291159#5291159 –

答えて

4

私はこれらの線に沿って何かが(未テスト、あなたのニーズに適合させなければならない)でください必要がありますね。これを行うための

$q = mysql_query("SELECT id, parent_id, name FROM categories"); 
while ($r = mysql_fetch_row($q)) { 
    $names[$r[0]] = $r[2]; 
    $children[$r[0]][] = $r[1]; 
} 

function render_select($root=0, $level=-1) { 
    global $names, $children; 
    if ($root != 0) 
    echo '<option>' . strrep(' ', $level) . $names[$root] . '</option>'; 
    foreach ($children[$root] as $child) 
    render_select($child, $level+1); 
} 

echo '<select>'; 
render_select(); 
echo '</select>'; 

も、ファンキーな方法は、SQLストアドプロシージャを使用することですが、それは仕方やり過ぎかもしれこの場合...

+0

無限の階層はどこですか? – Bytemain

+0

@David "無限の階層"がサポートされているので、コード内の再帰に明示的な停止条件はありません – CAFxX

+0

しかし、sqlクエリは再帰的ではありませんなぜ再帰関数が必要ですか? – Bytemain

0

これは答えではありませんが、多数の選択肢を使用する代わりに、多くの左結合を使用して4つの階層を横断することができます。代わりに、それだけでこの単一のクエリのコードのように多くの行で:

select a.id,a.parent_id,b.id,b.parent_id,c.id,c.parent_id,d.id,d.parent_id from a left join b ON a.id = b.parent_id left join c on b.id=c.parent_id left join d on c.id=d.parent_id; 

あなたは、テーブル名を別名設定できるので、あなたは、あまりにも、単一のテーブルで私のクエリを使用することができます。

left join mytable as c on c.id=d.parent_id ... ... 

しかしunfortunetley MySQLを再帰的選択をサポートしていません。たぶん別のデータベースを試してみてください。

+0

事は、これは1つのテーブルです。無制限の子カテゴリ数4 – nine7ySix

+0

@ nine7ySix:1つのテーブルもトラバースできます。エイリアスを使用するだけです。 – Bytemain

+0

@downvoter:なぜdownvote? – Bytemain

関連する問題