1


0

私はデータベース内のテーブルからツリー構造を生成しようとしています。 テーブルはフラットに格納され、各レコードはparent_idまたは0を持ちます。 最終的な目標は、選択ボックスとノードの配列を生成することです。

私がこれまでに持っているコードは次のとおりです。

関数init($テーブル、$ parent_id = 0){

$ sql = "SELECT id、{$ this-> parent_id_field}、{$ this-> name_field} $テーブルのどこから{$ this-> parent_id_field} = $ parent_id ORDER BY display_order";

$ result = mysql_query($ sql);

$ this-> get_tree($ result、0);

print_r($ this-> nodes); print_r($ this-> select);出口; }

function get_tree($ query、$ depth = 0、$ parent_obj = null){while($ row = mysql_fetch_object($ query)){/ *ノードを取得* / $ this-> nodes [$ row-> parent_category_id] [$ row - > id] = $ row;

/ *選択アイテムを取得* / $ text = ""; if($ row-> parent_category_id!= 0){$ text。= ""; $ text。= "$ row-> name"; $ this-> select [$ row-> id] = $ text;

echo "$ depth $ text \ n";

$ sql = "SELECT id、parent_category_id、name from product_categories WHERE parent_category_id ="。$ row-> id。 "ORDER BY display_order";

$ nextQuery = mysql_query($ sql); $ rows = mysql_num_rows($ nextQuery);

if($ rows> 0){$ this-> get_tree($ nextQuery、$ depth、$ row); }}}

それはほとんど動作していますが、それほどではありません。 誰かが私がそれを終わらせるのを手伝ってくれる?

3 Answer


4


あなたはほぼ確実に、現在の道を歩み続けるべきではありません。 あなたが使用しようとしている再帰的な方法は、あなたのツリーがこれより少し大きくなったとしても、ほぼ確実にあなたのパフォーマンスを殺すでしょう。 ツリーを頻繁に読むことを計画しているのであれば、おそらく隣接リストの代わりにネストされた集合構造を見るべきでしょう。

ネストされたセットを使用すると、単一のクエリで適切にネストされたツリー全体を簡単に取得できます。

木についての議論はこれらの質問を見てください。

https://stackoverflow.com/questions/544632/implementing-a-hierarchical-data-structure-in-a-database[データベース内の階層データ構造を実装する]


1


$ this-> nodes [$ row-> parent_category_id] [$ row-> id] = $ row;

この行はあなたのORDER BY display_orderを破壊しています。 に変更

$ this-> nodes [$ row-> parent_category_id] [] = $ row;

私の次の号はその中の$ row→ parent_category_idの部分です。 それは単に$ row→ parent_idであるべきではありませんか?

編集:ああ、私はあなたの情報源を十分に詳しく読みませんでした。 WHERE句を取り除きます。 テーブル全体を一度に読んでください。 もう一度ツリーをポストプロセスする必要があります。 最初にデータベースを配列のリストに読み込みます。 その後、配列を再帰的に処理して出力を行います。

あなたの配列は次のようになります。

Array(0 => Array(1 => $ obj、5 => $ obj)、1 => Array(2 => $ obj)、2 => Array(3 =>​​ $ obj、4 => $ obj)、 5 =>配列(6 => $ obj));

function display_tree(){// output_treeより上のものすべて($ this-> nodes [0]、0); // parent_id = 0の配列をすべて渡す }

function output_tree($ nodes、$ depth = 0){foreach($ kは$ k => $ v){echo str_repeat( ''、$ depth * 2)。 $ v-> print_me(); //サブツリーを出力するoutput_tree($ this-> nodes [$ k]、$ depth 1); }}

出力:オブジェクト1オブジェクト2オブジェクト3オブジェクト4オブジェクト5オブジェクト6


0


私はそれがこの行だと思います:

if($ row-> parent_category_id!= 0){$ text。= ""; }

する必要があります:

while($ depth--> 0){$ text。= ""; }

インデントする回数ではなく、一度だけインデントします。

そしてこの行:

$ this-> get_tree($ nextQuery、$ depth、$ row);

する必要があります:

$ this-> get_tree($ nextQuery、$ depth 1、$ row);

ただし、通常はデータベースへのラウンドトリップを最小限に抑えたいので、他の回答のアドバイスに従って、テーブル全体を一度に取得してからすぐに処理する必要があります(いくつかのユースケースがあります)。あなたがそれをしている方法は、あなたが非常に大きな木を持っていて、そしてそれの小さい部分を選んでいるかのように、もっと最適である、しかし私はそれがここに当てはまるのではないか?