Make hierarchy in PHP array in cycle
I've been fighting for hours with such a problem. For speeding my web-page I request database to get all categories just one time and then want to sort the array using PHP.
Array
(
[0] 开发者_运维问答=> Array
(
[id] => 1
[name] => name1
[parent] => 0
[children] =>
)
[1] => Array
(
[id] => 2
[name] => name2
[parent] => 1
[children] =>
)
)
I need to get something like this
Array
(
[0] => Array
(
[id] => 1
[name] => name1
[parent] => 0
[children] => Array
(
[id] => 2
[name] => name2
[parent] => 1
[children] =>
)
)
)
The problem with that is making it for any level of hierarchy. So that it could work in cycle. Please help!
There are lots of solutions to reducing the overhead here. But without knowing what your constraints are, it's difficult to recommend an approach.
e.g.:
use an adjacency model - see my comment on dnagirl's answer
load all the data into PHP then use a recursion algorithm to create the nested tree (this will be rather slow and would benefit from some caching)
write a recursive stored procedure which returns the result set sorted by a depth-first tree walk
Taking example 2 a bit closer to code....something like....
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
You're using an adjacency model for your hierarchy. You will either have to query your db multiple times, or if the number of levels is known, construct a union query with a clause for each level.
If it is allowed, you'll likely find that an AJAX solution where child levels are called when the parent is clicked is both easier to program and more efficient.
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;
}
This expects parents to always be populated before its children
What you are looking for is called recursion, as for me it is not very clear how to handle recursions in php and documentation is almost blank regarding this subject.
You might be interested to check this and this article
Not sure if you've found an answer yet, but I was looking for the same solution today and finally ended up making my own solution. The below code is the class I just created and it works with PHP arrays and objects and is recursive to an unlimited number of dimensions.
GitHub
https://github.com/DukeOfMarshall/PHP-Array-Heirarchy-Display
A simple example of using this code would be:
<?php
require_once('Arrays.class.php');
$display = new Array_Functions();
$display->display_hierarchy($multidimensional_array);
?>
There are other options that can be set as well, but that was just a straight up heirarchal display of an array or object.
<?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 ' ';
}
}
}
# 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;
}
}
?>
精彩评论