Question

Je suis en train de récupérer mes données qui est hiérarchiquement mis en place un modèle traversal d'arbre dans un

    afin de montrer sur mon site.

    Voici mon code:

    function getCats($) {
      // retrieve all children of $parent
      $query = "SELECT max(rght) as max from t_categories";
      $row = C_DB::fetchSingleRow($query);
      $max = $row["max"];
      $result ="<ul>";
      $query = "SELECT * from t_categories where lft >=0 and rght <= $max";
      if($rs = C_DB::fetchRecordset($query)){
        $p_right ="";
        $p_left ="";
        $p_diff="";          
        while($row = C_DB::fetchRow($rs)){
          $diff = $row["rght"] -$row["lft"];
    
          if($diff == $p_diff){
            $result.= "<li>".$row['title']."</li>";
          }elseif (($row["rght"] - $row["lft"] > 1) && ($row["rght"] > $p_right)){
            $result. "<ul>";
            $result.= "<li>".$row['title']."</li>";
    
          }else{
            $result.= "<li>".$row['title']."</li>";
          } 
    
          $p_right = $row["rght"];
          $p_left = $row["lft"];
          $p_diff = $diff;
        }
      }
      $result.= "</ul>";
      return $result;
    } 
    

    Voici ma table exemple:

    |ID  |  TITLE | lft| rght |
    |1   | Cat 1  | 1      |    16       |
    |18  | Cat 2  | 3      |    4       |
    |22  | Cat 3  | 5      |    6       |
    |28  | Cat 4  | 7      |    8       |
    |34  | Cat 5  | 9      |    9       |
    |46  | Cat 6  | 11      |    10       |
    |47  | Cat 7  | 13      |    12       |
    |49  | Cat 8  | 15      |    14       | 
    

    Maintenant, il sort quelque chose comme:

        <ul>
    <li>Cat 1</li>
    <li>Cat 2</li>
    <li>Cat 3</li>
    <li>Cat 4</li>
    <li>Cat 5</li>
    <li>Cat 6</li>
    <li>Cat 7</li>
    <li>Cat 8</li>
    </ul>
    

    Quelqu'un peut-il me dire pourquoi ou comment il va afficher la liste dans une structure hiérarchique?

    Rubrique connexe

Était-ce utile?

La solution

Ok, nous allons faire une chasse aux primes;)

Étape 0 - Désinfectez exemple: Comme déjà mentionné, votre exemple des données est cassé, car il ne définit pas un ensemble imbriqué valide. Si vous avez pris ces données à partir d'une application, vous devriez vérifier l'insertion / suppression logique.

pour le test, j'ai utilisé une version aseptisée comme ceci:
(MySQL ici, comme ce fut le premier à la main)

CREATE TABLE t_categories`(
  `id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
  `title` VARCHAR(45) NOT NULL,
  `lft` INTEGER UNSIGNED NOT NULL,
  `rght` INTEGER UNSIGNED NOT NULL,
  PRIMARY KEY (`id`)
);

INSERT INTO t_categories (title, lft, rght) VALUES ('Cat 1',1,16);
INSERT INTO t_categories (title, lft, rght) VALUES ('Cat 2',2,3);
INSERT INTO t_categories (title, lft, rght) VALUES ('Cat 3',4,7);
INSERT INTO t_categories (title, lft, rght) VALUES ('Cat 4',5,6);
INSERT INTO t_categories (title, lft, rght) VALUES ('Cat 5',8,13);
INSERT INTO t_categories (title, lft, rght) VALUES ('Cat 6',9,12);
INSERT INTO t_categories (title, lft, rght) VALUES ('Cat 7',10,11);
INSERT INTO t_categories (title, lft, rght) VALUES ('Cat 8',14,15);

Étape 1 - Laissez la base de données font la commande Emboîtées ensembles où principalement inventées comme un moyen pratique de stocker des arbres dans des bases de données, comme ils le font assez facile à interroger pour, sous-arborescences relations avec les parents et, particulièrement intéressant dans ce cas, pour l'ordre et la profondeur:

SELECT node.title, (COUNT(parent.title) - 1) AS depth
 FROM t_categories AS node
 CROSS JOIN t_categories AS parent
 WHERE node.lft BETWEEN parent.lft AND parent.rght
 GROUP BY node.title
 ORDER BY node.lft

Ceci renverra votre ensemble soigneusement ordonné, en commençant par le nœud racine et en continuant à la fin en précommande. Plus important encore, il ajoutera la profondeur de chaque noeud comme un entier positif, ce qui indique le nombre de niveaux du nœud est inférieure à la racine (niveau 0). Pour les données d'exemple ci-dessus, le résultat sera:

title, depth
'Cat 1', 0
'Cat 2', 1
'Cat 3', 1
'Cat 4', 2
'Cat 5', 1
'Cat 6', 2
'Cat 7', 3
'Cat 8', 1

Dans le code:

// Grab ordered data
$query = '';
$query .= 'SELECT node.title, (COUNT(parent.title) - 1) AS depth';
$query .= ' FROM t_categories AS node';
$query .= ' CROSS JOIN t_categories AS parent';
$query .= ' WHERE node.lft BETWEEN parent.lft AND parent.rght';
$query .= ' GROUP BY node.title';
$query .= ' ORDER BY node.lft';

$result = mysql_query($query);

// Build array
$tree = array();
while ($row = mysql_fetch_assoc($result)) {
  $tree[] = $row;
}

Le tableau résultant ressemblera à ceci:

Array
(
    [0] => Array
        (
            [title] => Cat 1
            [depth] => 0
        )

    [1] => Array
        (
            [title] => Cat 2
            [depth] => 1
        )
    ...
)

Étape 2 - Sortie en tant que fragment de liste HTML:

Utilisation en boucle:

// bootstrap loop
$result = '';
$currDepth = -1;  // -1 to get the outer <ul>
while (!empty($tree)) {
  $currNode = array_shift($tree);
  // Level down?
  if ($currNode['depth'] > $currDepth) {
    // Yes, open <ul>
    $result .= '<ul>';
  }
  // Level up?
  if ($currNode['depth'] < $currDepth) {
    // Yes, close n open <ul>
    $result .= str_repeat('</ul>', $currDepth - $currNode['depth']);
  }
  // Always add node
  $result .= '<li>' . $currNode['title'] . '</li>';
  // Adjust current depth
  $currDepth = $currNode['depth'];
  // Are we finished?
  if (empty($tree)) {
    // Yes, close n open <ul>
    $result .= str_repeat('</ul>', $currDepth + 1);
  }
}

print $result;

Même logique que la fonction récursive:

function renderTree($tree, $currDepth = -1) {
  $currNode = array_shift($tree);
  $result = '';
  // Going down?
  if ($currNode['depth'] > $currDepth) {
    // Yes, prepend <ul>
    $result .= '<ul>';
  }
  // Going up?
  if ($currNode['depth'] < $currDepth) {
    // Yes, close n open <ul>
    $result .= str_repeat('</ul>', $currDepth - $currNode['depth']);
  }
  // Always add the node
  $result .= '<li>' . $currNode['title'] . '</li>';
  // Anything left?
  if (!empty($tree)) {
    // Yes, recurse
    $result .=  renderTree($tree, $currNode['depth']);
  }
  else {
    // No, close remaining <ul>
    $result .= str_repeat('</ul>', $currNode['depth'] + 1);
  }
  return $result;
}

print renderTree($tree);

Tous deux sortie la structure suivante:

<ul>
    <li>Cat 1</li>
    <li>
        <ul>
            <li>Cat 2</li>
            <li>Cat 3</li>
            <li>
                <ul>
                    <li>Cat 4</li>
                </ul>
            </li>
            <li>Cat 5</li>
            <li>
                <ul>
                    <li>Cat 6</li>
                    <li>
                        <ul>
                            <li>Cat 7</li>
                        </ul>
                    </li>
                </ul>
            </li>
            <li>Cat 8</li>
        </ul>
    </li>
</ul>

coin de Nitpickers: Naudé explicitement demandé <ul>, mais ordonné listes à puces !? Allez ...
; -)

Autres conseils

Mieux rendu d'arbre Fonction qui a fonctionné pour moi ( fonction php pour préparer la source html pour une utilisation dans le plugin jsTree jQuery ) au lieu de son Henrik Opel:

function MyRenderTree ( $tree = array(array('name'=>'','depth'=>'')) ){

$current_depth = 0;
$counter = 0;

$result = '<ul>';

foreach($tree as $node){
    $node_depth = $node['depth'];
    $node_name = $node['name'];
    $node_id = $node['category_id'];

    if($node_depth == $current_depth){
        if($counter > 0) $result .= '</li>';            
    }
    elseif($node_depth > $current_depth){
        $result .= '<ul>';
        $current_depth = $current_depth + ($node_depth - $current_depth);
    }
    elseif($node_depth < $current_depth){
        $result .= str_repeat('</li></ul>',$current_depth - $node_depth).'</li>';
        $current_depth = $current_depth - ($current_depth - $node_depth);
    }
    $result .= '<li id="c'.$node_id.'"';
    $result .= $node_depth < 2 ?' class="open"':'';
    $result .= '><a href="#"><ins>&nbsp;</ins>'.$node_name.'</a>';
    ++$counter;
}
 $result .= str_repeat('</li></ul>',$node_depth).'</li>';

$result .= '</ul>';

return $result;}

Résultat HTML:

<ul>
    <li id="c1" class="open"><a href="#"><ins>&nbsp;</ins>ELECTRONICS</a>
        <ul>
            <li id="c2" class="open"><a href="#"><ins>&nbsp;</ins>TELEVISIONS</a>
                <ul>
                    <li id="c3"><a href="#"><ins>&nbsp;</ins>TUBE</a></li>
                    <li id="c4"><a href="#"><ins>&nbsp;</ins>LCD</a></li>
                    <li id="c5"><a href="#"><ins>&nbsp;</ins>PLASMA</a>
                        <ul>
                            <li id="c14"><a href="#"><ins>&nbsp;</ins>PLASMA1</a></li>
                            <li id="c15"><a href="#"><ins>&nbsp;</ins>PLASMA2</a></li>
                        </ul>
                    </li>
                </ul>
            </li>
            <li id="c6" class="open"><a href="#"><ins>&nbsp;</ins>PORTABLE ELECTRONICS</a>
                <ul>
                    <li id="c7"><a href="#"><ins>&nbsp;</ins>MP3 PLAYERS</a>
                        <ul>
                            <li id="c8"><a href="#"><ins>&nbsp;</ins>FLASH</a></li>
                        </ul>
                    </li>
                    <li id="c9"><a href="#"><ins>&nbsp;</ins>CD PLAYERS</a></li>
                    <li id="c10"><a href="#"><ins>&nbsp;</ins>2 WAY RADIOS</a></li>
                </ul>
            </li>
        </ul>
    </li>
</ul>

Il y a un paquet PEAR pour traiter les ensembles imbriqués:. DB_NestedSet
Vous pourriez également être intéressé par l'article Gestion des données hiérarchiques dans MySQL .

Ce devrait être ce que vous cherchez:

function getCats($left = null, $right = null)
{
    $sql = array();
    $result = null;

    if (isset($left) === true)
    {
        $sql[] = 'lft >= ' . intval($left);
    }

    if (isset($right) === true)
    {
        $sql[] = 'rght <= ' . intval($right);
    }

    if (empty($sql) === true)
    {
        $sql[] = 'lft = 1';
    }

    $sql = 'SELECT * FROM t_categories WHERE ' . implode(' AND ', $sql) . ';';

    if ($rs = C_DB::fetchRecordset($sql))
    {
        // you need to make sure that the query returns
        // something to correctly display the ULs
        if (empty($rs) === false)
        {
            $result .= '<ul>' . "\n";

            while ($row = C_DB::fetchRow($rs))
            {
                $result .= '<li>' . $row['title'] . '</li>' . "\n";
                $result .= getCats($row['lft'], $row['rght']);
            }

            $result .= '</ul>' . "\n";
        }
    }

    return $result;
}

Pour obtenir le code HTML de votre arbre imbriqué vous devez faire:

echo getCats();

S'il vous plaît noter que votre échantillon de jeu imbriqué ne semble pas juste, vous devriez également vous assurer que si je ne fait aucune erreur en invoquant votre classe C_DB, je ne sais pas puisque je ne suis pas familiarisé avec elle.

boucle simplement à travers le résultat fera:

$sql = "SELECT node.name, (COUNT(parent.name) - 1) AS depth
        FROM nested_category AS node,
        nested_category AS parent
        WHERE node.lft BETWEEN parent.lft AND parent.rgt
        GROUP BY node.name
        ORDER BY node.lft";

$query_result = mysql_query($sql)

$result = "<ul>";
$currDepth = 0;

while($row = mysql_fetch_assoc($query_result))
{
  if($row['depth'] > $currDepth)
  {
    $result .= "<li><ul>"; // open sub tree if level up
  }

  if($row['depth'] < $currDepth)
  {
    $result .= str_repeat("</ul></li>", $currDepth - $row['depth']); // close sub tree if level down
  }

  $result .= "<li>$row['name']</li>"; // Always add node
  $currDepth = $row['depth'];
}
$result .= "</ul>";

echo $result;
$linaje='';
    $lastnode='';
    $sides['izq']=array();
    $sides['der']=array();
    $print = '<ul>'; 
    foreach ($array as $key1 => $value1){ //Proyectos

        if(strpos($info[$key1]['linaje'],'-') !== false)
            $compare = strstr($info[$key1]['linaje'],'-',true);
        else
            $compare  = $info[$key1]['linaje'];

        if($linaje != ''){
            if ($linaje !=   $compare){
                $linaje= $compare;
                $sides['izq']=array();
                $sides['der']=array();
                //for($i=1;$i <= substr_count($lastnode,'`')-substr_count($value1,'`');$i++)
                    //$print .= '</ul></li>';
            }
        }


        if ($lastnode != '')
            for($i=1;$i<= substr_count($lastnode,'`')-substr_count($value1,'`');$i++)
                $print .= '</ul></li>'; 

        if (count($sides['der'])>0)
            if  ($sides['der'][count($sides['der'])-1] > $info[$key1]['der'])
                $print .= '<ul>';

        $print .= '<li><a href="#'.$info[$key1]['id'].'#'.$info[$key1]['linaje'].'">'.substr($value1,substr_count($value1,'`')).'</a>';

        if  ($info[$key1]['der'] - $info[$key1]['izq'] == 1)
                $print .= '</li>';

        if ($key1 == count($info)-1)
            for($i=1;$i <= substr_count($lastnode,'`')-1;$i++)
                $print .= '</ul></li>';

        $sides['der'][] = $info[$key1]['der'];
        $sides['izq'][] = $info[$key1]['izq'];

        if ($linaje =='')
                $linaje = $info[$key1]['linaje'];

        $lastnode = $value1;
    }
    $print .= '</ul>';
    echo $print;

la différence est que vous pouvez rendre le nombre X d'arbres, cela s'applique à un de mes projets. et j'utilise un produit de carbonisation en tant que référence de profondeur lorsque je vais chercher les lignes de la DB

i`m en utilisant CROSS JOIN requête affichage du menu jsTree jQuery; Tout fonctionne tout simplement génial! Le tableau I existante a ajouté une colonne pour la position. Cependant, quand je définir la position et commandé tout par la position, les éléments correspondants ne sont pas regroupés correctement. Je suppose que c'est une question de requête, essayé beaucoup de combinaisons, mais sans succès.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top