2012-04-23 5 views
4

私のウェブサイトにツリービューリストを作成する2つの関数があります。これは再帰に基づいており、無制限のノード数でツリービューを構築することができます。PHPを使用して折りたたみ可能なツリービューリストを作成することは可能です(JSなし)

しかし、私は折りたたむことができません。たとえば、スクリプトはかどうかを判断し、そうであれば、ブロック要素とそのすべての親を表示(展開)します。だから、私はその "表示"パラメータをルートに渡す必要があります。

事は$display$display2ヴァルスです。

  • 私は3つの列(id、parent_id、name)を持つ古典的なdbテーブルを持っています。ルートノードには、parent_idフィールドが入力されていません。
  • hrefはGETパラメータにリンクしています。 GETパラメータはノード番号を意味します。

この折りたたみ技術は、どのノードiが選択されたかに基づいて動作する必要があります。

更新日: いいえ、完全で浄化された情報があります。 データベースを扱うphpファイルを作成しましたが、これには1つのテーブルのみが含まれています。

1私はsqlite3データベース形式を使用しています。これはDBダンプです:

 

     # sqlite3 catalog.sqlite .dump 
    PRAGMA foreign_keys=OFF; 
    BEGIN TRANSACTION; 
    CREATE TABLE groups(id INTEGER PRIMARY KEY NOT NULL, name TEXT, parent_id INTEGER); 
    INSERT INTO "groups" VALUES(1,'root1',''); 
    INSERT INTO "groups" VALUES(2,'root2',''); 
    INSERT INTO "groups" VALUES(3,'root3',''); 
    INSERT INTO "groups" VALUES(4,'root4',''); 
    INSERT INTO "groups" VALUES(5,'sub1',1); 
    INSERT INTO "groups" VALUES(6,'sub3',3); 
    INSERT INTO "groups" VALUES(7,'subsub1',5); 
    INSERT INTO "groups" VALUES(8,'subsubsub1',7); 
    INSERT INTO "groups" VALUES(9,'subb1',1); 
    COMMIT; 

2これは、databseを扱うPHPファイルです。

<?php 

$db = new SQLite3('catalog.sqlite'); 

function build_catalog($db){ //build roots and diggs for childnodes for every root in a loop 
    //$content_root="<ul id='collapsedlist'>"; 
    $content_root = ''; 
    $roots = $db->query('SELECT * from groups WHERE parent_id="" OR parent_id is null'); 
    while($root = $roots->fetchArray()){ 
     list ($content,$display)=get_children_of_node($db,$root['id']); 
     $content_root .= "<li id='".$root['id']."' ><a href='/?node=".$root['id']."'>".$root['name']."</a>"; 
     $content_root .= $content; 
     $content_root .= "</li>\n"; 
    } 
    $content_root = "<ul id='collapsedlist'>".$content_root."</ul>\n"; 

    return $content_root; 
} 

function get_children_of_node($db,$node_id){ 
    if(!isset($content)) $content = ''; 
    $display = (isset($_GET['node']) && $_GET['node'] == $node_id)? "style='display:block'" : "style='display:none'"; 
    $query = $db->querySingle('SELECT count(*) from groups WHERE parent_id='.$node_id); 
    if ($query > 0){ 
     //$content .= "<ul class='subcategories'>\n"; 
     $children = $db->query('SELECT * from groups WHERE parent_id =\''.$node_id.'\''); 
     while ($child = $children->fetchArray()){ 
      list($content2,$display)=get_children_of_node($db,$child['id']); 
      $content .= "<li id='".$child['id']."' ".$display.">"; 
      $content .= "<a href='/?node=".$child['id']."'>".$child['name']."</a>"; 
      $content .= $content2; 
      $content .= "</li>\n"; 
     } 
     $content = "<ul class='subcategories' ".$display.">".$content."</ul>\n"; 
    } 
    return array($content,$display); 
} 


?> 

ここで、phpファイルは、上記の純粋なHTMLで終了します。私はそれをここから別のものに分けたので、エディタはHTML + PHP構文を一度に解析できません。同じindex.phpファイルです。 HTML部分:

<html> 
    <head> 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
    <title>Collapsible Nested List</title> 
    </head> 
    <body> 
     <div id="sidebar"> 
      <?=build_catalog($db);?> 
     </div> 
    </body> 
    </html> 
+0

親カラムは 'parent_id'と言いましたが、スクリプト全体で' parend_id'が使用されています。それが正しいと思いますか? – halfer

+0

はい、問題ありません。 DBにテーブルを作成したのは間違いでした。とにかくドラフトです。ロジックは正常に動作していますが、私は表示に関する情報を渡す必要がありますか、上のレベルに折りたたみ可能なdinamicallyで表示するブロックを表示する。現在、すべてのノードがデフォルトとして表示されるので、すべてのサブカテゴリの非集約リストが表示されます。 – remort

+0

私はより多くの情報を提供することができます。テーブル構造、スクリーンショットなどがあります。私は知っているので、再帰は理解するのが難しいです)) – remort

答えて

3

ここでは、単に次のコードを使用してPHPを置き換える同じHTMLを保ち、あなたの問題への迅速なソリューションです。

function get_children($db, $parent_id) { 
    $res = $db->query("SELECT * FROM groups WHERE parent_id='$parent_id'"); 
    if (!$res) return array(); 

    $out = array(); 
    while ($row = $res->fetchArray(SQLITE3_ASSOC)) $out[$row['id']] = $row; 
    return $out; 
} 

function get_parent_id($db, $node_id) { 
    return $db->querySingle("SELECT parent_id FROM groups WHERE id='$node_id'"); 
} 

function get_menu($db, $node_id) { 
    $menu = get_children($db, $node_id); 
    while (($parent_id = get_parent_id($db, $node_id)) !== null) { 
     $temp = get_children($db, $parent_id); 
     $temp[$node_id]['children'] = $menu; 
     $menu = $temp; 
     $node_id = $parent_id; 
    } 
    return $menu; 
} 

function build_html(array $menu) { 
    $str = ''; 
    foreach ($menu as $id => $item) { 
     $str .= sprintf('<li><a href="?node=%s">%s</a></li>', $id, $item['name']); 
     if (isset($item['children'])) 
      $str .= build_html($item['children']); 
    } 
    return "<ul>$str</ul>"; 
} 

function build_catalog($db) { 
    $menu = get_menu($db, isset($_GET['node']) ? intval($_GET['node']) : ''); 
    return build_html($menu); 
} 

「グループ」テーブルが非常に小さい場合、このコードは実際に最適化できます。アイデアは、すべてのレコードを$ groups配列に取得し、parent_idインデックスを作成することです。カタログの構築はずっと簡単です。

+0

ああ、たわごと!それはちょうど素晴らしい作品です!本当にありがとう、本当にありがとう))私はあなたのコードにもっと近づくだろう...「グループが「小さい」ならば、「最適化ロジック」について何を言っているのかを教えてください。この表は巨大で、多くの子供を含んでいる可能性があります。たとえば、多くのカテゴリを持つWebショップのカタログです。 – remort

+0

良い努力、+1。 – halfer

+1

考えられるのは、データベースに対して行われるクエリの数を最小限に抑えることです。この例では、深さ3のノードの場合、コードは各ページビューでデータベースに2 * 4のクエリを行い、IMHOではこれが悪いです。これを最適化するには少なくとも2つの方法があります。 1)左、右、および深度の列(Doctrine Tree Behavior、複雑なクエリ&挿入ロジックなど)でツリーを構築します。 2)配列全体を取り出して(メモリを食べる)。ウェブショップのカテゴリはあまり「巨大」ではありません。あなたが100のカテゴリを持っているとしましょう、これは既に素晴らしいカタログを作成しています... – smrtl