2009-04-14 8 views
2

ネストされたリストについて多くの人が読んできましたが、PHPの隣接リスト/ツリーをどのように反復するのかと思いました。単一テーブルの隣接ツリー

私が持つテーブルがあります:ID、タイトルは、

をPARENT_IDそして私は$ページと呼ばれる配列にすべてのレコードを選択しました。その後

このPHPを使用して:作品のこの種の

function makeList($pages, $used) { 
    if (count($pages)) { 
     echo "<ul>"; 
     foreach ($pages as $page) { 
      echo "<li>".$page['pag_title']; 
      $par_id = $page['pag_id']; 
      $subsql("SELECT * FROM pages WHERE pag_parent = ".$par_id.""); 

      // running the new sql through an abstraction layer 
      $childpages = $dbch->fetchAll(); 
      makeList($childpages, $used, $lastused); 
      echo "</li>"; 
     } 
     echo "</ul>"; 
    } 
} 

を私は例えば繰り返されている任意のサブメニューで終わります

  • ホーム
    • ニュース
      • サブニュース
    • 記事
  • ニュース
    • サブニュース
  • 記事
  • サブニュース

は私が機能を通じて渡される配列に、現在のIDを追加し、それがあるかどうかをチェックするin_array使用してみましたが、私はそれをやって何の喜びを持っていませんでした。

ご協力いただければ幸いです。私は0として親を選んツリー全体を解析する必要が

は、最も簡単な修正はちょうどあなたが(あなたが表示されません)$pagesを設定する最初の選択を行っている際に、だろうオプション

答えて

1

すでにSQLを実行しているので、最初の関数呼び出しの前に外部で行う必要はありません。

function makeList($par_id = 0) { 
    //your sql code here 
    $subsql("SELECT * FROM pages WHERE pag_parent = $par_id"); 
    $pages = $dbch->fetchAll(); 

    if (count($pages)) { 
     echo '<ul>'; 
     foreach ($pages as $page) { 
      echo '<li>', $page['pag_title']; 
      makeList($page['pag_id']); 
      echo '</li>'; 
     } 
     echo '</ul>'; 
    } 
} 

あなたはこのサイトを見てみたいかもしれません:Storing Hierarchical Data in a Database

+0

ありがとうございます – Del

+2

あまりにも多くのクエリが必要になります。 –

+0

@SamDarkはい、私は個人的にはより階層的なデータを保存します。 – OIS

0

ではありません

WHERE pag_parent = 0 

(または「トップレベル」ページの格納方法に応じて、IS NULL)などのWHERE句を追加します。

これで、最初にすべての子供を選択することはありません。

0

$ページはどこから来ますか?エスケープしたり、準備されたステートメントを使用していない場合は、コードにSQLインジェクションの脆弱性が存在する可能性があります。

また、forループ内のSELECT文も悪い習慣として飛び出します。テーブルがそれほど大きくなければ、テーブル全体の内容を選択し、PHPの結果セットを反復処理してツリーデータ構造を構築します。これは、ツリーの病理学的なケースでは、リンクされたリストであるn *(n-1)/ 2回の反復までかかることがあります。すべてのノードがツリーに追加されたときに停止するか、残りのノードの数が1つの反復から次の反復まで同じになると、残りのノードはルートノードの子ではありません。

データベースが再帰的SQLクエリをサポートしている場合は、これを使用して、親ノードの子ノードのみを選択します。 PHPでツリーオブジェクトを自分で構築する必要があります。クエリの形式は次のようになります。

WITH temptable(id, title, parent_id) AS (
    SELECT id, title, parent_id FROM pages WHERE id = ? 
    UNION ALL 
    SELECT a.id, a.title, a.parent_id FROM pages a, temptable t 
    WHERE t.parent_id = a.id 
) SELECT * FROM temptable 

「?'を開始ページIDとともに2行目に追加します。

+0

$ページは$から来ていますpages配列は、それ自体がsqlから来ています(sqlの選択は別のクラスで行われ、すべてがSQLインジェクションを避けるためにエスケープされています)。それは私が興味を持っているPHPですが、SQLではなく、 – Del

2

親IDでグループ化されたページの配列を作成すると、再帰的にリストを構築するのは簡単です。これは1つのデータベースクエリを必要とします。

<?php 

//example data 
$items = array(
    array('id'=>1, 'title'=>'Home', 'parent_id'=>0), 
    array('id'=>2, 'title'=>'News', 'parent_id'=>1), 
    array('id'=>3, 'title'=>'Sub News', 'parent_id'=>2), 
    array('id'=>4, 'title'=>'Articles', 'parent_id'=>0), 
    array('id'=>5, 'title'=>'Article', 'parent_id'=>4), 
    array('id'=>6, 'title'=>'Article2', 'parent_id'=>4) 
); 

//create new list grouped by parent id 
$itemsByParent = array(); 
foreach ($items as $item) { 
    if (!isset($itemsByParent[$item['parent_id']])) { 
     $itemsByParent[$item['parent_id']] = array(); 
    } 

    $itemsByParent[$item['parent_id']][] = $item; 
} 

//print list recursively 
function printList($items, $parentId = 0) { 
    echo '<ul>'; 
    foreach ($items[$parentId] as $item) { 
     echo '<li>'; 
     echo $item['title']; 
     $curId = $item['id']; 
     //if there are children 
     if (!empty($items[$curId])) { 
      makeList($items, $curId); 
     }   
     echo '</li>'; 
    } 
    echo '</ul>'; 
} 

printList($itemsByParent); 
0

、すべての親、およびノー​​ドのすべての子(トム・ヘーグの答えのための機能強化):

<?php 

//sample data (can be pulled from mysql) 
$items = array(
    array('id'=>1, 'title'=>'Home', 'parent_id'=>0), 
    array('id'=>2, 'title'=>'News', 'parent_id'=>1), 
    array('id'=>3, 'title'=>'Sub News', 'parent_id'=>2), 
    array('id'=>4, 'title'=>'Articles', 'parent_id'=>0), 
    array('id'=>5, 'title'=>'Article', 'parent_id'=>4), 
    array('id'=>6, 'title'=>'Article2', 'parent_id'=>4) 
); 

//create new list grouped by parent id 
$itemsByParent = array(); 
foreach ($items as $item) { 
    if (!isset($itemsByParent[$item['parent_id']])) { 
     $itemsByParent[$item['parent_id']] = array(); 
    } 

    $itemsByParent[$item['parent_id']][] = $item; 
} 

//print list recursively 
function printList($items, $parentId = 0) { 
    echo '<ul>'; 
    foreach ($items[$parentId] as $item) { 
     echo '<li>'; 
     echo $item['title']; 
     $curId = $item['id']; 
     //if there are children 
     if (!empty($items[$curId])) { 
      printList($items, $curId); 
     }   
     echo '</li>'; 
    } 
    echo '</ul>'; 
} 

printList($itemsByParent); 


/***************Extra Functionality 1****************/ 

function findTopParent($id,$ibp){ 


    foreach($ibp as $parentID=>$children){ 

      foreach($children as $child){ 


      if($child['id']==$id){ 


      if($child['parent_id']!=0){ 

      //echo $child['parent_id']; 
      return findTopParent($child['parent_id'],$ibp); 

      }else{ return $child['title'];} 

     }    
     } 
} 
} 

$itemID=7; 
$TopParent= findTopParent($itemID,$itemsByParent); 





/***************Extra Functionality 2****************/ 

function getAllParents($id,$ibp){ //full path 

foreach($ibp as $parentID=>$nodes){ 

    foreach($nodes as $node){ 

     if($node['id']==$id){ 

      if($node['parent_id']!=0){ 

       $a=getAllParents($node['parent_id'],$ibp); 
       array_push($a,$node['parent_id']); 
       return $a; 

       }else{ 
        return array(); 
        } 

      } 
    } 
} 
} 


$FullPath= getAllParents(3,$itemsByParent); 
print_r($FullPath); 

/* 
Array 
(
[0] => 1 
[1] => 2 
) 
*/ 

/***************Extra Functionality 3****************/ 

//this function gets all offspring(subnodes); children, grand children, etc... 
function getAllDescendancy($id,$ibp){ 

if(array_key_exists($id,$ibp)){ 

     $kids=array(); 
     foreach($ibp[$id] as $child){ 

      array_push($kids,$child['id']); 

      if(array_key_exists($child['id'],$ibp)) 

$kids=array_merge($kids,getAllDescendancy($child['id'],$ibp)); 

      } 

     return $kids;  

    }else{ 
      return array();//supplied $id has no kids 
      } 
} 

print_r(getAllDescendancy(1,$itemsByParent)); 
/* 
Array 
(
[0] => 2 
[1] => 3 
) 
*/ 


print_r(getAllDescendancy(4,$itemsByParent)); 
/* 
Array 
(
[0] => 5 
[1] => 6 
) 
*/ 


print_r(getAllDescendancy(0,$itemsByParent)); 
/* 
Array 
(
[0] => 1 
[1] => 2 
[2] => 3 
[3] => 4 
[4] => 5 
[5] => 6 
) 

*/ 

?> 
関連する問題