PHP - Как получить доступ к содержимому глубокого массива, динамически выстраивая путь к нему

Я пытаюсь построить иерархический массив в PHP из содержимого реляционной базы данных, которое хранится с использованием таблицы замыканий. Для данного результата у меня будет полный путь к узлу LEAF, ниже будет выглядеть мой набор результатов.

1 ~ корень ~ корневой узел

1 ~ root ~ корневой узел>> 2 ~ category1 ~ первая категория

1 ~ root ~ корневой узел>> 3 ~ category2 ~ Вторая категория

1 ~ корневой ~ корневой узел>> 2 ~ category1 ~ первая категория>>>> 4 ~ subCatOfCategory1 ~ подкатегория Cat 1

В любом случае, это результаты моей базы данных. Поэтому я хочу обойти их и построить иерархическую структуру в PHP, чтобы я мог преобразовать ее в JSON и отобразить дерево в DOJO

Поэтому, проходя по каждой строке, я строю «путь» к листу, потому что мне нужно добавлять элемент в дерево только тогда, когда этот элемент является «листом» ... После этого я решил, что буду токенизировать каждый результат, используя ">>>" в качестве разделителя, давая мне узлы, которые находятся в этом ряду. Затем я перебираю эти узлы, разбивая каждый из них на «~», что дает мне атрибуты каждого узла.

Итак, у меня есть цикл for для обработки каждой строки, и он в основном определяет, что если обрабатываемый узел НЕ является листом, добавьте его идентификатор в массив, который должен отслеживать путь, чтобы добраться до конечного листа, который будет обработанный. Затем, когда я наконец приду к LEAF, я смогу вызвать функцию для вставки узла, используя путь, который я скомпилировал по пути.

Надеюсь, что все это имеет смысл ... поэтому я включил приведенный ниже код. Рассмотрим второй результат, приведенный выше. Когда я обработал весь этот результат и собираюсь вызвать функцию insertNodeInTreeV2 (), массивы выглядят так, как показано ниже ...

$fullTree - это массив с 1 элементом, индексированный как [1] Этот элемент содержит массив из четырех элементов: ID(1), NAME(root), Description(the root node), CHILDREN(empty array)

$pathEntries - это массив только с одним элементом (1). Это означает, что путь PATH к вставляемому узлу LEAF осуществляется узлом [1], который является корневым узлом.

$nodeToInsert - это массив из четырех элементов: ID(2), NAME(category1), Description(First Category) , CHILDREN(empty array)

$treeRootPattern - это STRING, содержащая имя переменной, которую я использую для хранения всего массива /дерева, что в данном случае "fullTree".

private function insertNodeInTreeV2( array &$fullTree, array $pathEntries, array $nodeToInsert, $treeRootPattern )
{
  $compiledPath = null;
  foreach ( $pathEntries as $path ) {
    $compiledPath .= $treeRootPattern . '[' . $path . '][\'CHILDREN\']';
  }
  // as this point $compiledPath = "fullTree[1]['CHILDREN']"
  $treeVar = $$compiledPath;
}

Поэтому, когда я делаю назначение, $ treeVar = $$ compiledPath ;, я думаю, я устанавливаю переменную $ treeVar равной $ fullTree [1] ['CHILDREN'] (которую я проверил в моем отладчике: действительный индекс массива). Даже если я вставлю содержимое $ compiledPath в новый отладчик Expression в Eclipse, он покажет мне пустой массив, что имеет смысл, потому что это то, что находится в $ fullTree [1] ['CHILDREN']

Но вместо этого среда выполнения сообщает мне следующую ошибку ...

  

troller.php строка 85 - неопределенная переменная: fullTree [1] ['CHILDREN']

Любая помощь по этому вопросу будет принята с благодарностью ... И если у вас есть лучший способ для меня перейти от набора результатов, который я описал, к иерархическому массиву, который я пытаюсь построить, я бы очень хотел принять лучший метод.

ОБНОВЛЕНО, ЧТОБЫ ДОБАВИТЬ КОД, КОТОРЫЙ ВЫЗЫВАЕТ ВЫШЕЮ ФУНКЦИЮ - ДЛЯ ПРОЦЕССОВ ЦИКЛА, СТРОКИ РЕЗУЛЬТАТОВ БАЗЫ ДАННЫХ, КАК ОПИСАНО НАД

foreach ( $ontologyEntries as $entry ) {

        // iterating over rows of  '1~~root~~The root node>>>2~~category1~~The first category
        $nodes = explode( '>>>', $entry['path'] );
        $numNodes = count( $nodes ) - 1 ;

        $pathToNewNode = null;  // this is the path, based on ID, to get to this *new* node
        for ( $level = 0; $level <= $numNodes; $level++ ) {

            // Parse the node out of the database search result
            $thisNode = array(
                'ID'          => strtok($nodes[$level], '~~'),  /*   1   */
                'NAME'        => strtok( '~~'),                 /*   Root   */
                'DESCRIPTION' => strtok( '~~'),                 /*   This is the root node   */
                'CHILDREN'    => array()
            );

            if ( $level < $numNodes ) {   // Not a leaf, add it to the pathToThisNodeArray
                $pathToNewNode[] = $thisNode['ID'];
            }
            else {
                // processing a leaf, add it to the array
                $this->insertNodeInTreeV2( $$treeRootPattern,  $pathToNewNode, $thisNode, $treeRootPattern );
            }

        }

    }
4 голоса | спросил rogodeter 5 AMpThu, 05 Apr 2012 02:41:46 +040041Thursday 2012, 02:41:46

1 ответ


0

См. мои комментарии под вашим вопросом для объяснения.

$paths = array(
    "1~root~the root node",
    "1~root~the root node>>>2~category1~First category",
    "1~root~the root node>>>3~category2~Second category",
    "1~root~the root node>>>2~category1~First category>>>4~subCatOfCategory1~SubCategory of Cat 1"
);

$tree = array();

foreach ($paths as $path)
{
    $currentNode = &$tree;

    $parts = explode(">>>", $path);

    foreach ($parts as $part)
    {
         $node = explode("~", $part);

         // create all nodes along this path
         if (!isset($currentNode[$node[0]]))
         {
              $currentNode[$node[0]] = array(
                "ID"            => $node[0],
                "NAME"          => $node[1],
                "DESCRIPTION"   => $node[2],
                "CHILDREN"      => array(),
              );
         }

         $currentNode = &$currentNode[$node[0]]["CHILDREN"];
    }
}

var_dump($tree);

Выходы:

array
  1 => 
    array
      'ID' => string '1' (length=1)
      'NAME' => string 'root' (length=4)
      'DESCRIPTION' => string 'the root node' (length=13)
      'CHILDREN' => 
        array
          2 => 
            array
              'ID' => string '2' (length=1)
              'NAME' => string 'category1' (length=9)
              'DESCRIPTION' => string 'First category' (length=14)
              'CHILDREN' => 
                array
                  4 => 
                    array
                      'ID' => string '4' (length=1)
                      'NAME' => string 'subCatOfCategory1' (length=17)
                      'DESCRIPTION' => string 'SubCategory of Cat 1' (length=20)
                      'CHILDREN' => &
                        array
                          empty
          3 => 
            array
              'ID' => string '3' (length=1)
              'NAME' => string 'category2' (length=9)
              'DESCRIPTION' => string 'Second category' (length=15)
              'CHILDREN' => 
                array
                  empty

Цикл создаст все узлы, которые включены в путь, поэтому вам не нужно вставлять 1~root~the root node, если вы также вставить 1~root~the root node>>>2~category1~First category.

Вы можете изменить это, только создавая узлы, если узел является последним узлом пути. Длина пути составляет count($parts), и вы можете подсчитать, на каком уровне вы находитесь во внутреннем цикле foreach.

Я надеюсь, что это то, что вы хотели.

ответил Basti 5 AMpThu, 05 Apr 2012 03:30:18 +040030Thursday 2012, 03:30:18

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132