Transformer une série de relations parent-enfant en arbre hiérarchique?

j'ai un tas de couples nom-parentnom, que j'aimerais transformer en aussi peu de structures d'arbres hérarchiques que possible. Ainsi, par exemple, ceux-ci pourraient être les appariements:

Child : Parent
    H : G
    F : G
    G : D
    E : D
    A : E
    B : C
    C : E
    D : NULL

qui doit être transformé en (a) arbre(s) généalogique (s):

D
├── E
│   ├── A
│   │   └── B
│   └── C   
└── G
    ├── F
    └── H

le résultat final que je veux est un ensemble imbriqué de <ul> éléments, avec chaque <li> contenant le nom de l'enfant.

il n'y a pas des incohérences dans les liaisons (l'enfant est son propre parent, parent de l'enfant, etc), donc, un tas d'optimisations peuvent probablement être fait.

comment, en PHP, pourrais-je passer d'un tableau contenant les paires child=>parent, à un ensemble de <ul> imbriqués?

j'ai le sentiment que la récursion est impliquée, mais je ne suis pas assez éveillé pour y réfléchir.

91
demandé sur Mr. Polywhirl 2010-05-26 22:39:22

8 réponses

cela nécessite une fonction récursive très basique pour analyser les paires enfant / parent à une structure d'arbre et une autre fonction récursive pour l'imprimer. Une seule fonction suffirait, mais en voici deux pour plus de clarté (une fonction combinée se trouve à la fin de cette réponse).

initialiser D'abord le tableau de paires enfant/parent:

$tree = array(
    'H' => 'G',
    'F' => 'G',
    'G' => 'D',
    'E' => 'D',
    'A' => 'E',
    'B' => 'C',
    'C' => 'E',
    'D' => null
);

puis la fonction qui divise ce tableau dans une structure d'arbre hiérarchique:

function parseTree($tree, $root = null) {
    $return = array();
    # Traverse the tree and search for direct children of the root
    foreach($tree as $child => $parent) {
        # A direct child is found
        if($parent == $root) {
            # Remove item from tree (we don't need to traverse this again)
            unset($tree[$child]);
            # Append the child into result array and parse its children
            $return[] = array(
                'name' => $child,
                'children' => parseTree($tree, $child)
            );
        }
    }
    return empty($return) ? null : $return;    
}

et une fonction qui traverse cet arbre pour imprimer une liste non ordonnée:

function printTree($tree) {
    if(!is_null($tree) && count($tree) > 0) {
        echo '<ul>';
        foreach($tree as $node) {
            echo '<li>'.$node['name'];
            printTree($node['children']);
            echo '</li>';
        }
        echo '</ul>';
    }
}

et l'usage réel:

$result = parseTree($tree);
printTree($result);

voici le contenu de $result :

Array(
    [0] => Array(
        [name] => D
        [children] => Array(
            [0] => Array(
                [name] => G
                [children] => Array(
                    [0] => Array(
                        [name] => H
                        [children] => NULL
                    )
                    [1] => Array(
                        [name] => F
                        [children] => NULL
                    )
                )
            )
            [1] => Array(
                [name] => E
                [children] => Array(
                    [0] => Array(
                        [name] => A
                        [children] => NULL
                    )
                    [1] => Array(
                        [name] => C
                        [children] => Array(
                            [0] => Array(
                                [name] => B
                                [children] => NULL
                            )
                        )
                    )
                )
            )
        )
    )
)

si vous voulez un peu plus d'efficacité, vous pouvez combiner ces fonctions en une seule et réduire le nombre d'itérations effectuées:

function parseAndPrintTree($root, $tree) {
    $return = array();
    if(!is_null($tree) && count($tree) > 0) {
        echo '<ul>';
        foreach($tree as $child => $parent) {
            if($parent == $root) {                    
                unset($tree[$child]);
                echo '<li>'.$child;
                parseAndPrintTree($child, $tree);
                echo '</li>';
            }
        }
        echo '</ul>';
    }
}

vous n'économiserez que 8 itérations sur un ensemble de données aussi petit que cela, mais sur de plus grands ensembles, il pourrait faire une différence.

116
répondu Tatu Ulmanen 2013-08-11 10:02:37

encore une autre fonction pour faire un arbre (aucune récursion impliquée, utilise des références à la place):

$array = array('H' => 'G', 'F' => 'G', ..., 'D' => null);

function to_tree($array)
{
    $flat = array();
    $tree = array();

    foreach ($array as $child => $parent) {
        if (!isset($flat[$child])) {
            $flat[$child] = array();
        }
        if (!empty($parent)) {
            $flat[$parent][$child] =& $flat[$child];
        } else {
            $tree[$child] =& $flat[$child];
        }
    }

    return $tree;
}

renvoie un tableau hiérarchique comme celui-ci:

Array(
    [D] => Array(
        [G] => Array(
            [H] => Array()
            [F] => Array()
        )
        ...
    )
)

qui peut facilement être imprimé comme une liste HTML en utilisant la fonction recursive.

52
répondu Alexander Konstantinov 2010-05-26 19:34:28

un autre moyen simplifié de transformer la structure plate du $tree en une hiérarchie. Un seul réseau temporaire est nécessaire pour l'exposer:

// add children to parents
$flat = array(); # temporary array
foreach ($tree as $name => $parent)
{
    $flat[$name]['name'] = $name; # self
    if (NULL === $parent)
    {
        # no parent, is root element, assign it to $tree
        $tree = &$flat[$name]; 
    }
    else
    {
        # has parent, add self as child    
        $flat[$parent]['children'][] = &$flat[$name];
    }
}
unset($flat);

C'est tout pour l'obtention de la hiérarchie dans un tableau multidimensionnel:

Array
(
    [children] => Array
        (
            [0] => Array
                (
                    [children] => Array
                        (
                            [0] => Array
                                (
                                    [name] => H
                                )

                            [1] => Array
                                (
                                    [name] => F
                                )

                        )

                    [name] => G
                )

            [1] => Array
                (
                    [name] => E
                    [children] => Array
                        (
                            [0] => Array
                                (
                                    [name] => A
                                )

                            [1] => Array
                                (
                                    [children] => Array
                                        (
                                            [0] => Array
                                                (
                                                    [name] => B
                                                )

                                        )

                                    [name] => C
                                )

                        )

                )

        )

    [name] => D
)

le résultat est moins trivial si vous voulez éviter la récursion (peut être un fardeau avec de grandes structures).

j'ai toujours voulu résoudre le "dilemme" UL/LI pour la sortie d'un tableau. Le dilemme est que chaque élément ne sait pas si les enfants feront ou non un suivi ou combien d'éléments précédents doivent être fermés. Dans une autre réponse, j'ai déjà résolu cela en utilisant un RecursiveIteratorIterator et en recherchant getDepth() et d'autres méta-informations que mon propre écrit Iterator fourni: obtenir imbriqué modèle de série dans un <ul> mais se cacher "fermé" sous-arbres . Que réponse montre ainsi qu'avec les itérateurs vous êtes assez souple.

cependant c'était une liste pré-triée, donc ne serait pas approprié pour votre exemple. De plus, j'ai toujours voulu résoudre cela pour une sorte de structure d'arbre standard et des éléments HTML <ul> et <li> .

le concept de base que j'ai développé est le suivant:

  1. TreeNode - résumé de chaque élément en un simple TreeNode type qui peut fournir sa valeur (par exemple Name ) et si oui ou non il a des enfants.
  2. TreeNodesIterator - un RecursiveIterator qui est capable d'itérer sur un ensemble (tableau) de ces TreeNodes . C'est assez simple car le type TreeNode sait déjà s'il a des enfants et lesquels.
  3. RecursiveListIterator - Un RecursiveIteratorIterator qui a tous les événements nécessaires quand il itérate récursivement sur tout type de RecursiveIterator :
    • beginIteration / endIteration - début et fin de la liste principale.
    • beginElement / endElement - début et fin de chaque élément.
    • beginChildren / endChildren - début et fin de chaque liste d'enfants. Ce RecursiveListIterator ne fournit ces événements que sous forme d'appels de fonction. les listes d'enfants, comme c'est typique pour les listes <ul><li> , sont ouvertes et fermées à l'intérieur, c'est l'élément parent <li> . Par conséquent, l'événement endElement est déclenché après l'événement endChildren . Ce pourrait être modifié ou rendu configurable pour élargir l'utilisation de cette classe. Les événements sont distribués comme des appels de fonction à un objet décorateur alors, pour garder les choses à part.
  4. ListDecorator - une classe de " décorateur "qui est juste un récepteur des événements de RecursiveListIterator .

je commence par la logique de sortie principale. Pris dans le tableau $tree , le code final ressemble à ce qui suit:

$root = new TreeNode($tree);
$it = new TreeNodesIterator(array($root));
$rit = new RecursiveListIterator($it);
$decor = new ListDecorator($rit);
$rit->addDecorator($decor);

foreach($rit as $item)
{
    $inset = $decor->inset(1);
    printf("%s%s\n", $inset, $item->getName());
}

regardons D'abord dans le ListDecorator qui enveloppe simplement les éléments <ul> et <li> et est en train de décider comment la structure de liste est sortie:

class ListDecorator
{
    private $iterator;
    public function __construct(RecursiveListIterator $iterator)
    {
        $this->iterator = $iterator;
    }
    public function inset($add = 0)
    {
        return str_repeat('  ', $this->iterator->getDepth()*2+$add);
    }

le constructeur prend l'itérateur de liste sur lequel il travaille. inset est juste un assistant fonction pour une bonne indentation de la sortie. Les autres ne sont que les fonctions de sortie pour chaque événement:

    public function beginElement()
    {
        printf("%s<li>\n", $this->inset());
    }
    public function endElement()
    {
        printf("%s</li>\n", $this->inset());
    }
    public function beginChildren()
    {
        printf("%s<ul>\n", $this->inset(-1));
    }
    public function endChildren()
    {
        printf("%s</ul>\n", $this->inset(-1));
    }
    public function beginIteration()
    {
        printf("%s<ul>\n", $this->inset());
    }
    public function endIteration()
    {
        printf("%s</ul>\n", $this->inset());
    }
}

avec ces fonctions de sortie à l'esprit, il s'agit de la sortie principale récapitulation / boucle à nouveau, je passe par elle étape par étape:

$root = new TreeNode($tree);

créer la racine TreeNode qui sera utilisé pour commencer l'itération sur:

$it = new TreeNodesIterator(array($root));

Ce TreeNodesIterator est un RecursiveIterator qui permet récursive d'une itération sur le seul noeud $root . Il est passé comme un tableau parce que cette classe a besoin de quelque chose pour itérer et permet la réutilisation avec un ensemble d'enfants qui est aussi un tableau d'éléments TreeNode .

$rit = new RecursiveListIterator($it);

Ce RecursiveListIterator est un RecursiveIteratorIterator qui fournit à ces événements. Pour l'utiliser, seul un ListDecorator doit être fourni (la classe ci-dessus) et attribué avec addDecorator :

$decor = new ListDecorator($rit);
$rit->addDecorator($decor);

alors tout est prêt pour juste foreach au-dessus de lui et la sortie de chaque noeud:

foreach($rit as $item)
{
    $inset = $decor->inset(1);
    printf("%s%s\n", $inset, $item->getName());
}

comme cet exemple le montre, toute la logique de sortie est encapsulée dans la classe ListDecorator et cette seule foreach . L'ensemble de la traversée récursive a été entièrement encapsulée dans des itérateurs récursifs SPL qui ont fourni une procédure empilée, ce qui signifie qu'en interne aucun appel de fonction de récursion n'est fait.

le ListDecorator basé sur l'événement vous permet de modifier la sortie en particulier et de fournir plusieurs types de listes pour la même structure de données. Il est même possible de changer l'entrée car les données du tableau ont été encapsulées dans TreeNode .

exemple de code complet:

<?php
namespace My;

$tree = array('H' => 'G', 'F' => 'G', 'G' => 'D', 'E' => 'D', 'A' => 'E', 'B' => 'C', 'C' => 'E', 'D' => null);

// add children to parents
$flat = array(); # temporary array
foreach ($tree as $name => $parent)
{
    $flat[$name]['name'] = $name; # self
    if (NULL === $parent)
    {
        # no parent, is root element, assign it to $tree
        $tree = &$flat[$name];
    }
    else
    {
        # has parent, add self as child    
        $flat[$parent]['children'][] = &$flat[$name];
    }
}
unset($flat);

class TreeNode
{
    protected $data;
    public function __construct(array $element)
    {
        if (!isset($element['name']))
            throw new InvalidArgumentException('Element has no name.');

        if (isset($element['children']) && !is_array($element['children']))
            throw new InvalidArgumentException('Element has invalid children.');

        $this->data = $element;
    }
    public function getName()
    {
         return $this->data['name'];
    }
    public function hasChildren()
    {
        return isset($this->data['children']) && count($this->data['children']);
    }
    /**
     * @return array of child TreeNode elements 
     */
    public function getChildren()
    {        
        $children = $this->hasChildren() ? $this->data['children'] : array();
        $class = get_called_class();
        foreach($children as &$element)
        {
            $element = new $class($element);
        }
        unset($element);        
        return $children;
    }
}

class TreeNodesIterator implements \RecursiveIterator
{
    private $nodes;
    public function __construct(array $nodes)
    {
        $this->nodes = new \ArrayIterator($nodes);
    }
    public function  getInnerIterator()
    {
        return $this->nodes;
    }
    public function getChildren()
    {
        return new TreeNodesIterator($this->nodes->current()->getChildren());
    }
    public function hasChildren()
    {
        return $this->nodes->current()->hasChildren();
    }
    public function rewind()
    {
        $this->nodes->rewind();
    }
    public function valid()
    {
        return $this->nodes->valid();
    }   
    public function current()
    {
        return $this->nodes->current();
    }
    public function key()
    {
        return $this->nodes->key();
    }
    public function next()
    {
        return $this->nodes->next();
    }
}

class RecursiveListIterator extends \RecursiveIteratorIterator
{
    private $elements;
    /**
     * @var ListDecorator
     */
    private $decorator;
    public function addDecorator(ListDecorator $decorator)
    {
        $this->decorator = $decorator;
    }
    public function __construct($iterator, $mode = \RecursiveIteratorIterator::SELF_FIRST, $flags = 0)
    {
        parent::__construct($iterator, $mode, $flags);
    }
    private function event($name)
    {
        // event debug code: printf("--- %'.-20s --- (Depth: %d, Element: %d)\n", $name, $this->getDepth(), @$this->elements[$this->getDepth()]);
        $callback = array($this->decorator, $name);
        is_callable($callback) && call_user_func($callback);
    }
    public function beginElement()
    {
        $this->event('beginElement');
    }
    public function beginChildren()
    {
        $this->event('beginChildren');
    }
    public function endChildren()
    {
        $this->testEndElement();
        $this->event('endChildren');
    }
    private function testEndElement($depthOffset = 0)
    {
        $depth = $this->getDepth() + $depthOffset;      
        isset($this->elements[$depth]) || $this->elements[$depth] = 0;
        $this->elements[$depth] && $this->event('endElement');

    }
    public function nextElement()
    {
        $this->testEndElement();
        $this->event('{nextElement}');
        $this->event('beginElement');       
        $this->elements[$this->getDepth()] = 1;
    } 
    public function beginIteration()
    {
        $this->event('beginIteration');
    }
    public function endIteration()
    {
        $this->testEndElement();
        $this->event('endIteration');       
    }
}

class ListDecorator
{
    private $iterator;
    public function __construct(RecursiveListIterator $iterator)
    {
        $this->iterator = $iterator;
    }
    public function inset($add = 0)
    {
        return str_repeat('  ', $this->iterator->getDepth()*2+$add);
    }
    public function beginElement()
    {
        printf("%s<li>\n", $this->inset(1));
    }
    public function endElement()
    {
        printf("%s</li>\n", $this->inset(1));
    }
    public function beginChildren()
    {
        printf("%s<ul>\n", $this->inset());
    }
    public function endChildren()
    {
        printf("%s</ul>\n", $this->inset());
    }
    public function beginIteration()
    {
        printf("%s<ul>\n", $this->inset());
    }
    public function endIteration()
    {
        printf("%s</ul>\n", $this->inset());
    }
}


$root = new TreeNode($tree);
$it = new TreeNodesIterator(array($root));
$rit = new RecursiveListIterator($it);
$decor = new ListDecorator($rit);
$rit->addDecorator($decor);

foreach($rit as $item)
{
    $inset = $decor->inset(2);
    printf("%s%s\n", $inset, $item->getName());
}

Outpupt:

<ul>
  <li>
    D
    <ul>
      <li>
        G
        <ul>
          <li>
            H
          </li>
          <li>
            F
          </li>
        </ul>
      </li>
      <li>
        E
        <ul>
          </li>
          <li>
            A
          </li>
          <li>
            C
            <ul>
              <li>
                B
              </li>
            </ul>
          </li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

Démo (PHP 5.2 variante)

une variante possible serait un itérateur qui itérate sur n'importe quel RecursiveIterator et fournit une itération sur tous les événements qui peuvent se produire. Un commutateur / boîtier à l'intérieur de la boucle foreach pourrait alors traiter les événements.

Related:

27
répondu hakre 2017-05-23 12:02:45

Eh bien, d'abord je voudrais transformer le tableau droit des paires de valeurs-clés en un tableau hiérarchique

function convertToHeiarchical(array $input) {
    $parents = array();
    $root = array();
    $children = array();
    foreach ($input as $item) {
        $parents[$item['id']] = &$item;
        if ($item['parent_id']) {
            if (!isset($children[$item['parent_id']])) {
                $children[$item['parent_id']] = array();
            }
            $children[$item['parent_id']][] = &$item;
        } else {
            $root = $item['id'];
        }
    }
    foreach ($parents as $id => &$item) {
        if (isset($children[$id])) {
            $item['children'] = $children[$id];
        } else {
            $item['children'] = array();
        }
    }
    return $parents[$root];
}

qui peut convertir un tableau plat avec parent_id et id en un tableau hiérarchique:

$item = array(
    'id' => 'A',
    'blah' => 'blah',
    'children' => array(
        array(
            'id' => 'B',
            'blah' => 'blah',
            'children' => array(
                array(
                    'id' => 'C',
                    'blah' => 'blah',
                    'children' => array(),
                ),
             ),
            'id' => 'D',
            'blah' => 'blah',
            'children' => array(
                array(
                    'id' => 'E',
                    'blah' => 'blah',
                    'children' => array(),
                ),
            ),
        ),
    ),
);

alors, il suffit de créer une fonction de rendu:

function renderItem($item) {
    $out = "Your OUtput For Each Item Here";
    $out .= "<ul>";
    foreach ($item['children'] as $child) {
        $out .= "<li>".renderItem($child)."</li>";
    }
    $out .= "</ul>";
    return $out;
}
8
répondu ircmaxell 2013-10-27 19:07:05

alors que Alexander-Konstantinov ' s solution pourrait ne pas sembler aussi facile à lire au début, il est à la fois génial et exponentiellement mieux en termes de performance, cela aurait dû être voté comme la meilleure réponse.

Merci mon pote, j'ai fait un benchmark en votre honneur pour comparer les 2 solutions présentées dans ce post.

j'ai eu un @250k arbre plat avec 6 niveaux que j'ai dû convertir et je cherchais une meilleure façon de le faire et récursives itérations.

récursion vs référence:

// Generate a 6 level flat tree
$root = null;
$lvl1 = 13;
$lvl2 = 11;
$lvl3 = 7;
$lvl4 = 5;
$lvl5 = 3;
$lvl6 = 1;    
$flatTree = [];
for ($i = 1; $i <= 450000; $i++) {
    if ($i % 3 == 0)  { $lvl5 = $i; $flatTree[$lvl6] = $lvl5; continue; }
    if ($i % 5 == 0)  { $lvl4 = $i; $flatTree[$lvl5] = $lvl4; continue; }
    if ($i % 7 == 0)  { $lvl3 = $i; $flatTree[$lvl3] = $lvl2; continue; }
    if ($i % 11 == 0) { $lvl2 = $i; $flatTree[$lvl2] = $lvl1; continue; }
    if ($i % 13 == 0) { $lvl1 = $i; $flatTree[$lvl1] = $root; continue; }
    $lvl6 = $i;
}

echo 'Array count: ', count($flatTree), PHP_EOL;

// Reference function
function treeByReference($flatTree)
{
    $flat = [];
    $tree = [];

    foreach ($flatTree as $child => $parent) {
        if (!isset($flat[$child])) {
            $flat[$child] = [];
        }
        if (!empty($parent)) {
            $flat[$parent][$child] =& $flat[$child];
        } else {
            $tree[$child] =& $flat[$child];
        }
    }

    return $tree;
}

// Recursion function
function treeByRecursion($flatTree, $root = null)
{
    $return = [];
    foreach($flatTree as $child => $parent) {
        if ($parent == $root) {
            unset($flatTree[$child]);
            $return[$child] = treeByRecursion($flatTree, $child);
        }
    }
    return $return ?: [];
}

// Benchmark reference
$t1 = microtime(true);
$tree = treeByReference($flatTree);
echo 'Reference: ', (microtime(true) - $t1), PHP_EOL;

// Benchmark recursion
$t2 = microtime(true);
$tree = treeByRecursion($flatTree);
echo 'Recursion: ', (microtime(true) - $t2), PHP_EOL;

le résultat parle pour lui-même:

Array count: 255493
Reference: 0.3259289264679 (less than 0.4s)
Recursion: 6604.9865279198 (almost 2h)
5
répondu NTT 2017-05-23 11:47:23

Eh bien, pour analyser en ULs et LIs, ce serait quelque chose comme:

$array = array (
    'H' => 'G'
    'F' => 'G'
    'G' => 'D'
    'E' => 'D'
    'A' => 'E'
    'B' => 'C'
    'C' => 'E'
    'D' => 'NULL'
);


recurse_uls ($array, 'NULL');

function recurse_uls ($array, $parent)
{
    echo '<ul>';
    foreach ($array as $c => $p)  {
        if ($p != $parent) continue;
        echo '<li>'.$c.'</li>';
        recurse_uls ($array, $c);
    }
    echo '</ul>';
}

mais j'aimerais voir une solution qui n'exige pas que vous itériez à travers le tableau si souvent...

2
répondu arnorhs 2010-05-26 19:05:16

voilà ce que j'ai trouvé:

$arr = array(
            'H' => 'G',
            'F' => 'G',
            'G' => 'D',
            'E' => 'D',
            'A' => 'E',
            'B' => 'C',
            'C' => 'E',
            'D' => null );

    $nested = parentChild($arr);
    print_r($nested);

    function parentChild(&$arr, $parent = false) {
      if( !$parent) { //initial call
         $rootKey = array_search( null, $arr);
         return array($rootKey => parentChild($arr, $rootKey));
      }else { // recursing through
        $keys = array_keys($arr, $parent);
        $piece = array();
        if($keys) { // found children, so handle them
          if( !is_array($keys) ) { // only one child
            $piece = parentChild($arr, $keys);
           }else{ // multiple children
             foreach( $keys as $key ){
               $piece[$key] = parentChild($arr, $key);
             }
           }
        }else {
           return $parent; //return the main tag (no kids)
        }
        return $piece; // return the array built via recursion
      }
    }

sorties:

Array
(
    [D] => Array
        (
            [G] => Array
                (
                    [H] => H
                    [F] => F
                )

            [E] => Array
                (
                    [A] => A
                    [C] => Array
                        (
                            [B] => B
                        )    
                )    
        )    
)
2
répondu Dan Heberden 2010-05-26 19:32:51

comment créer une vue D'arbre dynamique et Menu

Étape 1: Nous allons D'abord créer la table treeview dans la base de données mysql. cette table contient quatre colonnes.id est l'id de la tâche et nom est le nom de la tâche.

-
-- Table structure for table `treeview_items`
--

CREATE TABLE IF NOT EXISTS `treeview_items` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(200) NOT NULL,
  `title` varchar(200) NOT NULL,
  `parent_id` varchar(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ;

--
-- Dumping data for table `treeview_items`
--

INSERT INTO `treeview_items` (`id`, `name`, `title`, `parent_id`) VALUES
(1, 'task1', 'task1title', '2'),
(2, 'task2', 'task2title', '0'),
(3, 'task3', 'task1title3', '0'),
(4, 'task4', 'task2title4', '3'),
(5, 'task4', 'task1title4', '3'),
(6, 'task5', 'task2title5', '5');

Étape 2: méthode récursive de Tree view J'ai créé la méthode createtreview() qui appelle récursive si l'id de la tâche courante est supérieur à l'id de la tâche prev.

function createTreeView($array, $currentParent, $currLevel = 0, $prevLevel = -1) {

foreach ($array as $categoryId => $category) {

if ($currentParent == $category['parent_id']) {                       
    if ($currLevel > $prevLevel) echo " <ol class='tree'> "; 

    if ($currLevel == $prevLevel) echo " </li> ";

    echo '<li> <label for="subfolder2">'.$category['name'].'</label> <input type="checkbox" name="subfolder2"/>';

    if ($currLevel > $prevLevel) { $prevLevel = $currLevel; }

    $currLevel++; 

    createTreeView ($array, $categoryId, $currLevel, $prevLevel);

    $currLevel--;               
    }   

}

if ($currLevel == $prevLevel) echo " </li>  </ol> ";

}

Étape 3: Créer le fichier d'index pour afficher la vue d'arbre. C'est le fichier principal de treeview.exemple nous appellerons ici la méthode createtreview() avec les paramètres requis.

 <body>
<link rel="stylesheet" type="text/css" href="_styles.css" media="screen">
<?php
mysql_connect('localhost', 'root');
mysql_select_db('test');


$qry="SELECT * FROM treeview_items";
$result=mysql_query($qry);


$arrayCategories = array();

while($row = mysql_fetch_assoc($result)){ 
 $arrayCategories[$row['id']] = array("parent_id" => $row['parent_id'], "name" =>                       
 $row['name']);   
  }
?>
<div id="content" class="general-style1">
<?php
if(mysql_num_rows($result)!=0)
{
?>
<?php 

createTreeView($arrayCategories, 0); ?>
<?php
}
?>

</div>
</body>

Étape 4: créez le style de fichier CSS.CSS Ici nous écrirons toutes les classes CSS liées, actuellement j'utilise la liste de commande pour créer la vue d'arbre. vous pouvez également modifier le chemin de l'image ici.

img { border: none; }
input, select, textarea, th, td { font-size: 1em; }

/* CSS Tree menu styles */
ol.tree
{
    padding: 0 0 0 30px;
    width: 300px;
}
    li 
    { 
        position: relative; 
        margin-left: -15px;
        list-style: none;
    }
    li.file
    {
        margin-left: -1px !important;
    }
        li.file a
        {
            background: url(document.png) 0 0 no-repeat;
            color: #fff;
            padding-left: 21px;
            text-decoration: none;
            display: block;
        }
        li.file a[href *= '.pdf']   { background: url(document.png) 0 0 no-repeat; }
        li.file a[href *= '.html']  { background: url(document.png) 0 0 no-repeat; }
        li.file a[href $= '.css']   { background: url(document.png) 0 0 no-repeat; }
        li.file a[href $= '.js']        { background: url(document.png) 0 0 no-repeat; }
    li input
    {
        position: absolute;
        left: 0;
        margin-left: 0;
        opacity: 0;
        z-index: 2;
        cursor: pointer;
        height: 1em;
        width: 1em;
        top: 0;
    }
        li input + ol
        {
            background: url(toggle-small-expand.png) 40px 0 no-repeat;
            margin: -0.938em 0 0 -44px; /* 15px */
            height: 1em;
        }
        li input + ol > li { display: none; margin-left: -14px !important; padding-left: 1px; }
    li label
    {
        background: url(folder-horizontal.png) 15px 1px no-repeat;
        cursor: pointer;
        display: block;
        padding-left: 37px;
    }

    li input:checked + ol
    {
        background: url(toggle-small.png) 40px 5px no-repeat;
        margin: -1.25em 0 0 -44px; /* 20px */
        padding: 1.563em 0 0 80px;
        height: auto;
    }
        li input:checked + ol > li { display: block; margin: 0 0 0.125em;  /* 2px */}
        li input:checked + ol > li:last-child { margin: 0 0 0.063em; /* 1px */ }

Plus De Détails

0
répondu 2014-07-24 08:04:34