如何编写函数来获得树结构化输出

时间:2016-08-13 10:15:08

标签: php mysql function recursion

here

我有一张名为login的表格。在这里我有3列id,名称和参考。人们可以在网站上注册另一个人。 Adminno reference,因此ref值为0A & c属于管理员,因此其参考值为1B,D and Gunder A,因此他们的参考值为2E and Funder B而且一个人最多可以推荐3个人。 。我需要把这个输出放在像这样的表中

enter image description here

5 个答案:

答案 0 :(得分:3)

使用此代码获取所需的输出

<?php 
$connection = mysqli_connect('localhost', 'root', '', 'db_mani'); //connection

$sql = "SELECT * FROM users";
$result = mysqli_query($connection, $sql);
$usersArray = array();
if(mysqli_num_rows($result) > 0){
    while($row = mysqli_fetch_assoc($result)) {
        $usersArray[]= $row; ///will create array of users
    }
}           

function makeMenu($items, $parentId) //will create array in tree structure
{
    $menu = array_filter($items, function ($item) use ($parentId) {
        return     $item['ref'] == $parentId;
    });
    foreach ($menu as &$item) 
    {
        $subItems = makeMenu($items, $item['id']);
        if (!empty($subItems)) 
        {
            $item['child'] = $subItems;
        }
    }
    return $menu;
}

function print_users($usersArray,$ref = 'Admin')
{   
    $str ='<table border="1" width ="300" style="text-align:center;"><tr>';
    foreach($usersArray as $user)
    { 
        $str.='<td>'.$user['name'].' (Ref:'.$ref.')';
        if(!empty($user['child']))
        {
            $str.= print_users($user['child'],$user['name']);
        }
        $str.='</td>';
    }
    $str.='</tr></table>';
    return $str;      
}


$usersArray = makeMenu($usersArray,0); ///call with parent id 0 for first time, this will give usres in tree structure
echo print_users($usersArray); // print users
?>

最终结果:

enter image description here

数据库结构:

enter image description here

我希望这能解决你的问题。谢谢。

答案 1 :(得分:2)

基于@Manjeet Barnala的回答的改进,他的makeMenu函数迭代每个父查找的每个节点(调用array_filter),可以用单循环完成。打印机功能也有点简化。

<?php
/**
*/
error_reporting(E_ALL);
ini_set('display_errors',1);


if (false) { //Test data
$usersArray = [
     1 => ['name'=>'Admin','ref'=>0,'childs'=>[]]
   , 2 => ['name'=>'A','ref'=>1,'childs'=>[]]
   , 3 => ['name'=>'b','ref'=>2,'childs'=>[]]
   , 4 => ['name'=>'c','ref'=>1,'childs'=>[]]
   , 5 => ['name'=>'d','ref'=>4,'childs'=>[]]
   , 6 => ['name'=>'e','ref'=>2,'childs'=>[]]
   , 7 => ['name'=>'f','ref'=>2,'childs'=>[]]
   , 8 => ['name'=>'g','ref'=>4,'childs'=>[]]
   , 9 => ['name'=>'h','ref'=>4,'childs'=>[]]
];
    }
else {
    $connection = mysqli_connect('localhost', 'root', '', 'db_mani'); //connection

    $sql = "SELECT * FROM users";
    $result = mysqli_query($connection, $sql);
    $usersArray = array();
    if(mysqli_num_rows($result) > 0){
        while($row = mysqli_fetch_assoc($result)) {
            $row['childs'] = [];
            $usersArray[$row['id']]= $row; ///will create array of users
        }
    }

}
$roots = [];
foreach ($usersArray as $id => &$user) {
    if ( empty($user['ref']) ) {
        //empty parent mean's i'm a root node
        $roots[] = $id;
    }
    else {
        //uplink user to it's parents childs array
        $usersArray[$user['ref']]['childs'][] = $id;
    }
}

$htmlTableForm = function ($userId) use (&$usersArray,&$htmlTableForm) {
    $childs = count($usersArray[$userId]['childs']);
    $parent = $usersArray[$userId]['ref'];
    $text   = $usersArray[$userId]['name'] . ( 0 < $parent ? ('('.$usersArray[$parent]['name'].')') :'');
    if ( 1 > $childs) {
        return  $text;
    }
    $tblCode  = ['<table><tr ><td colspan="'.$childs.'">',$text,'</td></tr><tr>'];
    foreach($usersArray[$userId]['childs'] as $childId){
        $tblCode[] = '<td>'.$htmlTableForm($childId).'</td>';
    }
    $tblCode[] ='</tr></table>';
    return implode('',$tblCode);
};

//Question unclear about multiple roots goes into same table or separated , even possilbe to exists, so this is the simpliest case
echo $htmlTableForm($roots[0]);

答案 2 :(得分:1)

只需创建一个仅包含零(管理员参考)和空数组categories.id的数组refs。然后使用while tree非空的循环,并查询refs的所有人等于数组ref的第一个元素。在此查询之后,您将删除refs的第一个元素。将refs作为关键字的所有查询的前提放入ref。将所有人tree添加到id数组中。 这样就可以构建树。

下一步是可视化refs。只需编写辅助函数tree即可通过递归计算节点的所有子节点。需要这个hleper函数来计算countAllChildren($node)的{​​{1}}。现在你必须将树从根走到顶部/叶子并打印每个人(dnt忘记{{1}由colspan

计算

我希望这能让你朝着正确的方向前进。编码时玩得开心:)

答案 3 :(得分:0)

这个想法是制作一个二维数组。困难在于处理colspan,因为你需要移动到正确的行来编写你的单元格。这段代码似乎有效,但并未针对所有情况进行测试:

<?php

class Leaf {
    var $name;
    var $ref;
    var $depth;
    var $numChildren;

    var $i;
    function __construct($name, $ref) {
        $this->name = $name;
        $this->ref = $ref;
        $this->numChildren = 0;
    }

}

class Tree {
    var $arrayLeaves;
    var $refLeaves;
    var $matrix;
    var $maxRows;
    var $maxCols;

    function __construct() {
        $this->arrayLeaves = array ();
        $this->refLeaves = array ();
        $this->maxRows = 0;
        $this->maxCols = 0;
    }
    function addLeaf($id, $name, $ref) {
        $leaf = new Leaf ( $name, $ref );
        $this->arrayLeaves [$id] = $leaf;
        if (! isset ( $this->refLeaves [$ref] )) {
            $this->refLeaves [$ref] = array ();
        }
        if (isset ( $this->arrayLeaves [$ref] )) {
            $parent = $this->arrayLeaves [$ref];
            if (null != $parent) {
                $leaf->depth = $parent->depth + 1;
                $parent->numChildren ++;
            } else {
                $leaf->depth = 0;
            }
            if (($leaf->depth + 1) > $this->maxRows) {
                $this->maxRows = $leaf->depth + 1;
            }
        } else {
            $leaf->depth = 0;
            $this->maxRows = 1;

        }
        $this->refLeaves [$ref] [] = $id;
    }
    function colSpan($ind, $leaf) {
        $retval = 0;
        if ($leaf->numChildren == 0) {
            $retval = 1;
        } else {
            $retval = 0;
            foreach ( $this->refLeaves [$ind] as $ref ) {
                $retval += $this->colSpan ( $ref, $this->arrayLeaves [$ref] );
            }
        }
        return $retval;
    }
    function printLeaf($ind, $colId, $parent) {
        $leaf = $this->arrayLeaves [$ind];
        if (null != $leaf) {
            if (null == $parent) {
                $refName = "none";
            } else {
                $refName = $parent->name;
            }
            while ($this->matrix[$leaf->depth] [$colId] != "<td></td>")  { // unsure about that
                $colId++;
            }
            $colspan = $this->colSpan ( $ind, $leaf );
            $this->matrix [$leaf->depth] [$colId] = "<td colspan=\"" . $colspan . "\">{$leaf->name} (ref: $refName)</td>";
            for($i = $colId + 1; $i < ($colId + $colspan); $i ++) {
                $this->matrix [$leaf->depth] [$i] = ""; // remove <td></td>
            }
            for($col = 0; $col < count ( $this->refLeaves [$ind] ); $col ++) {
                $ref = $this->refLeaves [$ind] [$col];
                $this->printLeaf ( $ref, $col, $leaf );
            }
        }
    }


    function printLeaves() {
        $this->matrix = array ();
        $this->maxCols = $this->colSpan(0, $this->arrayLeaves [1]); 
        for($i = 0; $i < $this->maxRows; $i ++) {
            $this->matrix [$i] = array ();
            for($j = 0; $j < $this->maxCols; $j ++) {
                $this->matrix [$i] [$j] = "<td></td>";
            }
        }
        $this->printLeaf ( 1, 0, null );
        echo '<table border="1">';
        for($i = 0; $i < $this->maxRows; $i ++) {
            echo "<tr>";
            for($j = 0; $j < $this->maxCols; $j ++) {
                echo $this->matrix [$i] [$j];
            }
            echo "</tr>";
        }
        echo "</table>";
    }
}
?>
<html>
<head>
</head>
<body>
<?php
$tree = new Tree ();
$tree->addLeaf ( 1, 'admin', 0 );
$tree->addLeaf ( 2, 'A', 1 );
$tree->addLeaf ( 3, 'B', 2 );
$tree->addLeaf ( 4, 'C', 1 );
$tree->addLeaf ( 5, 'D', 2 );
$tree->addLeaf ( 6, 'E', 3 );
$tree->addLeaf ( 7, 'F', 3 );
$tree->addLeaf ( 8, 'G', 2 );

$tree->printLeaves ();

?>
</body>
</html>

答案 4 :(得分:-1)

// Fetch data from BD
// $options = $stmt->query("SELECT * FROM Options")->fetch_all(PDO::FETCH_ASSOC);

$nodes = array();
$roots = array();

// init nodes indexed by IDs
foreach ($options as $option) {
    $option['subIds'] = array(); // init subIds
    $nodes[$option['id']] = $option;
}

// build a recursive structure (by reference)
foreach ($options as $option) {
    if ($option['ref'] == 0) {
        $roots[] = $option['id']; // add a root
    } else {
        $nodes[$option['ref']]['subIds'][] = $option['id']; // add a subnode
    }
}

// build recursive HTML-List
function getSubtreeHTMLList($subOptionIds, $nodes) {
    $result = '<ul>';
    foreach ($subOptionIds as $optionsId) {
        $result .= '<li>';
        $result .= $nodes[$optionsId]['option_name'];
        if (count($nodes[$optionsId]['subIds'] > 0)) {
            $result .= getSubtreeHTMLList($nodes[$optionsId]['subIds'], $nodes);
        }
        $result .= '</li>';
    }
    $result .= '</ul>';
    return $result;
}

echo getSubtreeHTMLList($roots, $nodes);

结果将类似于:

  • 管理员
    • A
        • 电子
        • ˚F
      • d
  • C

Demo