Плоский массив PHP в дерево иерархии
у меня есть массив со следующими ключами
id
parent_id
name
пример массива:
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"
}
}
что я хотел бы сделать, это отобразить дерево иерархии с помощью этого массива, код, который у меня есть на данный момент, производит:
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
в идеале мне нужно произвести ниже результат, но с неограниченным уровнем:
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
код у меня есть до сих пор:
$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/>';
}
}
}
}
}
если бы кто-нибудь мог дать мне несколько советов о том, как этого достичь, это было бы много оцененный.
я нашел решение здесь:создать вложенный список из массива PHP для раскрывающегося списка выберите поле
3 ответов
вы должны использовать рекурсию.
вот пример кода:
$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));
вы можете проверить его по адресу:http://phpfiddle.org/main/code/1qy-5fj
или если вы хотите точную формат:
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;
}
можно использовать класс FlatToTreeConverter из вспомогательной библиотеки Gears:
<?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;
}
}
не уверен, что вы уже нашли ответ, но я искал то же самое решение сегодня и, наконец, сделал свое собственное решение. Приведенный ниже код-это класс, который я только что создал, и он работает с массивами и объектами 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 ' ';
}
}
}
# 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;
}
}
?>