在循环中使PHP数组中的层次结构

时间:2011-01-31 17:16:20

标签: php arrays hierarchical-data hierarchical

我已经因为这样的问题而奋斗了好几个小时。为了加速我的网页,我请求数据库只获取所有类别一次,然后想要使用PHP对数组进行排序。

Array
(
    [0] => Array
        (
            [id] => 1
            [name] => name1
            [parent] => 0
            [children] => 
        )
   [1] => Array
    (
        [id] => 2
        [name] => name2
        [parent] => 1
        [children] => 
    )
)

我需要得到类似的东西

Array
(
    [0] => Array
        (
            [id] => 1
            [name] => name1
            [parent] => 0
            [children] => Array
                  (
                      [id] => 2
                      [name] => name2
                      [parent] => 1
                      [children] => 
                  )
        )

)

问题在于它适用于任何级别的层次结构。这样它就可以在循环中工作。请帮忙!

5 个答案:

答案 0 :(得分:4)

这里有很多减少开销的解决方案。但是,如果不知道你的约束是什么,就很难推荐一种方法。

e.g:

  1. 使用邻接模型 - 请参阅我对dnagirl的回答的评论

  2. 将所有数据加载到PHP中,然后使用递归算法创建嵌套树(这将相当慢,并且可以从一些缓存中受益)

  3. 编写一个递归存储过程,该过程返回按深度优先树步行排序的结果集

  4. 将示例2更接近代码....类似....

     function build_tree(&$unsorted, $start_node)
     {
         $out=array();
         foreach($unsorted as $key=>$node) {
            if ($node['parent']==$start_node) {
                $node['children']=build_tree($unsorted, $key);
                unset($unsorted[$key]);
                $out[]=$node;
            }
         }
         return $out;
     } 
     $threaded_tree=build_tree($list_of_nodes, 0); // assumes that the root is the first element
    

答案 1 :(得分:0)

foreach ($dataFromMySQL as $e) {
    $all[$e['id']] = $e;
    $ref = &$all[$e['id'];
    if ($e['parent']) $all[$e['id']]['children'][] = $ref;
    else $hierarchy[$e['id']] = $ref;
}

这期望父母在孩子之前总是被填充

答案 2 :(得分:0)

您正在为层次结构使用邻接模型。您将需要多次查询数据库,或者如果已知级别数,则构造一个带有每个级别子句的联合查询。

如果允许,您可能会发现在单击父级时调用子级别的AJAX解决方案更易于编程且更高效。

答案 3 :(得分:0)

你正在寻找的东西叫做递归,对我而言,如何处理php中的递归并不是很清楚,文档对于这个主题几乎是空白的。

您可能有兴趣查看thisthis文章

答案 4 :(得分:0)

不确定您是否找到了答案,但我今天正在寻找相同的解决方案,最后我自己制定了自己的解决方案。下面的代码是我刚刚创建的类,它适用于PHP数组和对象,并且递归到无限数量的维度。

GitHub https://github.com/DukeOfMarshall/PHP-Array-Heirarchy-Display

使用此代码的一个简单示例是:

<?php

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

$display->display_hierarchy($multidimensional_array);

?>

还可以设置其他选项,但这只是数组或对象的直接层次显示。

<?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;
}
}

?>