2013-02-06 28 views
8

Tôi có một mảng với các phím sauFlat PHP Array Hierarchy Tree

id 
parent_id 
name 

Một mảng mẫu:

array(7) { 
    [0]=> 
    array(3) { 
    ["id"]=> 
    string(1) "4" 
    ["parent_id"]=> 
    string(1) "0" 
    ["name"]=> 
    string(16) "Top Level Page 4" 
    } 
    [1]=> 
    array(3) { 
    ["id"]=> 
    string(1) "5" 
    ["parent_id"]=> 
    string(1) "1" 
    ["name"]=> 
    string(19) "Second Level Page 1" 
    } 
    [2]=> 
    array(3) { 
    ["id"]=> 
    string(1) "6" 
    ["parent_id"]=> 
    string(1) "2" 
    ["name"]=> 
    string(19) "Second Level Page 2" 
    } 
    [3]=> 
    array(3) { 
    ["id"]=> 
    string(1) "7" 
    ["parent_id"]=> 
    string(1) "5" 
    ["name"]=> 
    string(18) "Third Level Page 1" 
    } 
    [4]=> 
    array(3) { 
    ["id"]=> 
    string(1) "3" 
    ["parent_id"]=> 
    string(1) "0" 
    ["name"]=> 
    string(16) "Top Level Page 3" 
    } 
    [5]=> 
    array(3) { 
    ["id"]=> 
    string(1) "2" 
    ["parent_id"]=> 
    string(1) "0" 
    ["name"]=> 
    string(16) "Top Level Page 2" 
    } 
    [6]=> 
    array(3) { 
    ["id"]=> 
    string(1) "1" 
    ["parent_id"]=> 
    string(1) "0" 
    ["name"]=> 
    string(16) "Top Level Page 1" 
    } 
} 

Những gì tôi muốn làm là hiển thị một cây phân cấp sử dụng mảng này, mã tôi hiện đang sản xuất:

Top Level Page 4 
--Second Level Page 1 
---Second Level Page 2 
----Third Level Page 1 
Top Level Page 3 
Top Level Page 2 
Top Level Page 1 

Lý tưởng nhất là tôi cần tạo ra kết quả dưới đây nhưng với unlimi mức ted:

Top Level Page 4 
-Second Level Page 1 
-Second Level Page 2 
--Third Level Page 1 
Top Level Page 3 
Top Level Page 2 
Top Level Page 1 

Code tôi có cho đến nay là:

$level = 1; 
     foreach ($data as $row) { 
      if ($row['parent_id'] == 0) { 
       echo $row['name'] . '<br/>'; 
      } else { 
       $level++; 
       foreach ($data as $m) { 
        if ($m['parent_id'] === $row['parent_id']) { 
         $c = 0; 
         $append = ''; 
         while ($c < $level) { 
          $append.="-"; 
          $c++; 
         } 
         echo $append . $row['name'] . '<br/>'; 
        } 
       } 
      } 
     } 
    } 

Nếu bất cứ ai có thể cho tôi một số gợi ý về cách để đạt được điều này nó sẽ được nhiều đánh giá cao.

Tôi đã tìm thấy giải pháp tại đây: Create nested list from PHP array for dropdown select field

+0

"Ý của bạn là: đệ quy"? – ficuscr

+0

http://stackoverflow.com/questions/8840319/build-a-tree-from-a-flat-array-in-php hoặc http://stackoverflow.com/questions/4216875/php-reorder-array-to -reflect-parent-id-hierarchy hoặc http://stackoverflow.com/questions/2915748/how-can-i-convert-a-series-of-parent-child-relationships-into-a-hierarchical-tre – ficuscr

Trả lời

31

Bạn nên sử dụng đệ quy.

Dưới đây là một dụ mã:

$datas = array(
    array('id' => 1, 'parent' => 0, 'name' => 'Page 1'), 
    array('id' => 2, 'parent' => 1, 'name' => 'Page 1.1'), 
    array('id' => 3, 'parent' => 2, 'name' => 'Page 1.1.1'), 
    array('id' => 4, 'parent' => 3, 'name' => 'Page 1.1.1.1'), 
    array('id' => 5, 'parent' => 3, 'name' => 'Page 1.1.1.2'), 
    array('id' => 6, 'parent' => 1, 'name' => 'Page 1.2'), 
    array('id' => 7, 'parent' => 6, 'name' => 'Page 1.2.1'), 
    array('id' => 8, 'parent' => 0, 'name' => 'Page 2'), 
    array('id' => 9, 'parent' => 0, 'name' => 'Page 3'), 
    array('id' => 10, 'parent' => 9, 'name' => 'Page 3.1'), 
    array('id' => 11, 'parent' => 9, 'name' => 'Page 3.2'), 
    array('id' => 12, 'parent' => 11, 'name' => 'Page 3.2.1'), 
    ); 

function generatePageTree($datas, $parent = 0, $depth=0){ 
    $ni=count($datas); 
    if($ni === 0 || $depth > 1000) return ''; // Make sure not to have an endless recursion 
    $tree = '<ul>'; 
    for($i=0; $i < $ni; $i++){ 
     if($datas[$i]['parent'] == $parent){ 
      $tree .= '<li>'; 
      $tree .= $datas[$i]['name']; 
      $tree .= generatePageTree($datas, $datas[$i]['id'], $depth+1); 
      $tree .= '</li>'; 
     } 
    } 
    $tree .= '</ul>'; 
    return $tree; 
} 

echo(generatePageTree($datas)); 

Bạn có thể kiểm tra nó tại địa chỉ: http://phpfiddle.org/main/code/1qy-5fj

Hoặc nếu bạn muốn định dạng chính xác:

function generatePageTree($datas, $parent = 0, $depth = 0){ 
    $ni=count($datas); 
    if($ni === 0 || $depth > 1000) return ''; // Make sure not to have an endless recursion 
    $tree = ''; 
    for($i=0; $i < $ni; $i++){ 
     if($datas[$i]['parent'] == $parent){ 
      $tree .= str_repeat('-', $depth); 
      $tree .= $datas[$i]['name'] . '<br/>'; 
      $tree .= generatePageTree($datas, $datas[$i]['id'], $depth+1); 
     } 
    } 
    return $tree; 
} 

Các thử nghiệm: http://phpfiddle.org/main/code/jw3-s1j

+0

Bạn là Đấng Cứu Rỗi. Cảm ơn ... +1 –

+0

Câu trả lời hay, nhưng nếu không có thêm trẻ em nào thì thêm phần tử ul trống. –

+0

Sửa giải pháp để ngăn chặn phần tử ul trống –

1

Không chắc chắn nếu bạn đã tìm thấy câu trả lời chưa, nhưng tôi đang tìm kiếm cùng một giải pháp ngày hôm nay và cuối cùng đã đưa ra giải pháp của riêng tôi. Đoạn mã dưới đây là lớp mà tôi vừa tạo và nó hoạt động với các mảng và các đối tượng PHP và đệ quy đến một số không giới hạn các tham số.

GitHubhttps://github.com/DukeOfMarshall/PHP-Array-Heirarchy-Display

Một ví dụ đơn giản của việc sử dụng đoạn mã này sẽ là:

<?php 

require_once('Arrays.class.php'); 
$display = new Array_Functions(); 

$display->display_hierarchy($multidimensional_array); 

?> 

Có những lựa chọn khác có thể được thiết lập như là tốt, nhưng đó chỉ là một thẳng màn heirarchal lên của một mảng hoặc đối tượng.

<?php 

class Array_Functions { 
public $number_of_tabs = 3; # The default number of tabs to use when branching out 
private $counter   = 0; # The counter to use for the number of tab iterations to use on the current branch 

public $display_square_brackets  = TRUE; 
public $display_squiggly_brackets = FALSE; 
public $display_parenthesis   = FALSE; 

public $display_apostrophe = TRUE; 
public $display_quotes  = FALSE; 

public function __construct(){ 
} 

/** 
* Displays the array in an organized heirarchy and even does so recursively 
* 
* $array ARRAY - The array to display in a heirarchy 
* 
* $key_bookends STRING - The character to place on either side of the array key when printed 
* @@ square - Displays a set of square brackets around the key (DEFAULT) 
* @@ squiggly - Displays a set of squiggly brackets around the key 
* @@ parenthesis - Displays a set of parenthesis around the key 
* @@ FALSE - Turns off the display of bookends around the array key 
* 
* $key_padding STRING - The padding to use around the array key with printed 
* @@ quotes - Pads the array key with double quotes when printed 
* @@ apostrophe - Pads the array key with apostrophes when printed (DEFAULT) 
* @@ FALSE - Turns off the display of padding around the array key 
* 
* $number_of_tabs_to_use INT - The number of tabs to use when a sub array within the array creates a branch in the heirarchy 
* 
*/ 
public function display_hierarchy($array, $key_bookends = '', $key_padding = '', $number_of_tabs_to_use = ''){ 
    # Convert the input to a JSON and then back to an array just to make sure we know what we're working with 
    $array = $this->convert_object_to_array($array); 

    # If the $array variable is still not an array, then error out. 
    # We're not going to fool around with your stupidity 
    if(gettype($array) != 'array'){ 
     echo 'Value submitted was '.strtoupper(gettype($array)).' instead of ARRAY or OBJECT. Only arrays or OBJECTS are allowed Terminating execution.'; 
     exit(); 
    } 

    # Establish the bookend variables 
    if($key_bookends != '' || !$key_bookends){ 
     if(strtolower($key_bookends) == 'square'){ 
      $this->display_square_brackets  = TRUE; 
      $this->display_squiggly_brackets = FALSE; 
      $this->display_parenthesis   = FALSE; 
     }elseif(strtolower($key_bookends) == 'squiggly'){ 
      $this->display_square_brackets  = TRUE; 
      $this->display_squiggly_brackets = TRUE; 
      $this->display_parenthesis   = FALSE; 
     }elseif(strtolower($key_bookends) == 'parenthesis'){ 
      $this->display_square_brackets  = FALSE; 
      $this->display_squiggly_brackets = FALSE; 
      $this->display_parenthesis   = TRUE; 
     }elseif(!$key_bookends){ 
      $this->display_square_brackets  = FALSE; 
      $this->display_squiggly_brackets = FALSE; 
      $this->display_parenthesis   = FALSE; 
     } 
    } 


    # Establish the padding variables 
    if($key_padding != '' || !$key_padding){ 
     if(strtolower($key_padding) == 'apostrophe'){ 
      $this->display_apostrophe = TRUE; 
      $this->display_quotes  = FALSE; 
     }elseif(strtolower($key_padding) == 'quotes'){ 
      $this->display_apostrophe = FALSE; 
      $this->display_quotes  = TRUE; 
     }elseif(!$key_padding){ 
      $this->display_apostrophe = FALSE; 
      $this->display_quotes  = FALSE; 
     } 
    }  

    # Establish variable for the number of tabs 
    if(isset($number_of_tabs_to_use) && $number_of_tabs_to_use != ''){ 
     $this->number_of_tabs = $number_of_tabs_to_use; 
    } 

    foreach($array as $key => $value){ 
     $this->insert_tabs(); 

     if(is_array($value)){ 
      echo $this->display_padding($key)." => {<BR>"; 

      $this->counter++; 
      $this->display_hierarchy($value); 
      $this->counter--; 
      $this->insert_tabs(); 
      echo '} <BR>'; 
     }else{ 
      echo $this->display_padding($key)." => ".$value.'<BR>'; 
     } 
    } 
} 

# Inserts tab spaces for sub arrays when a sub array triggers a branch in the heirarchy 
# Helps to make the display more human readable and easier to understand 
private function insert_tabs(){ 
    for($i=1; $i<=$this->counter; $i++){ 
     for($x=1; $x<=$this->number_of_tabs; $x++){ 
      echo '&emsp;'; 
     } 
    } 
} 

# Takes a PHP object and converts it to an array 
# Works with single dimension and multidimensional arrays 
public function convert_object_to_array($object){ 
    $object = json_decode(json_encode($object), TRUE); 
    return $object; 
} 

# Sets the displayed padding around the array keys when printed on the screen 
public function display_padding($value){ 
    $default_container = "['VALUE_TO_REPLACE']"; 

    $value = str_replace("VALUE_TO_REPLACE", $value, $default_container); 

    if($this->display_square_brackets){ 
    }elseif($this->display_squiggly_brackets){ 
     $value = str_replace('[', '{', $value); 
     $value = str_replace(']', '}', $value); 
    }elseif($this->display_parenthesis){ 
     $value = str_replace('[', '(', $value); 
     $value = str_replace(']', ')', $value); 
    }else{ 
     $value = str_replace('[', '', $value); 
     $value = str_replace(']', '', $value); 
    } 

    if($this->display_apostrophe){ 
    }elseif($this->display_quotes){ 
     $value = str_replace("'", '"', $value); 
    }else{ 
     $value = str_replace("'", '', $value); 
    } 

    return $value; 
} 
} 

?> 
2

Bạn có thể sử dụng FlatToTreeConverter class từ Gears thư viện helper:

<?php 
namespace Cosmologist\Gears\Collection; 
/** 
* Class able to convert a flat array with parent ID's to a nested tree 
*/ 
class FlatToTreeConverter 
{ 
    /** 
    * Convert a flat array with parent ID's to a nested tree 
    * 
    * @link http://blog.tekerson.com/2009/03/03/converting-a-flat-array-with-parent-ids-to-a-nested-tree/ 
    * 
    * @param array $array   Flat array 
    * @param string $idKeyName  Key name for the element containing the item ID 
    * @param string $parentIdKey  Key name for the element containing the parent item ID 
    * @param string $childNodesField Key name for the element for placement children 
    * 
    * @return array 
    */ 
    public static function convert(array $array, $idKeyName = 'id', $parentIdKey = 'parentId', $childNodesField = 'children') 
    { 
     $indexed = array(); 
     // first pass - get the array indexed by the primary id 
     foreach ($array as $row) { 
      $indexed[$row[$idKeyName]]     = $row; 
      $indexed[$row[$idKeyName]][$childNodesField] = array(); 
     } 
     // second pass 
     $root = array(); 
     foreach ($indexed as $id => $row) { 
      $indexed[$row[$parentIdKey]][$childNodesField][$id] = &$indexed[$id]; 
      if (!$row[$parentIdKey]) { 
       $root[$id] = &$indexed[$id]; 
      } 
     } 
     return $root; 
    } 
}