クロージャー テーブルを使用して格納されているリレーショナル データベースのコンテンツから、PHP で階層配列を構築しようとしています。特定の結果については、ノードへのフル パスLEAF
が表示されます。以下は結果セットのようになります。
1~ルート~ルートノード
1~ルート~ルートノード>>>2~category1~最初のカテゴリ
1~ルート~ルートノード>>>3~category2~2番目のカテゴリ
1~ルート~ルートノード>>>2~category1~最初のカテゴリ>>>4~subCatOfCategory1~Cat 1のSubCategory
とにかく、それらは私のデータベースの結果です。だから私はそれらをトラバースし、PHP で階層構造を構築して、それを JSON に変換し、DOJO でツリーをレンダリングできるようにしたいと考えています。
要素が「リーフ」である場合にのみツリーに要素を追加する必要があるため、各行をたどってリーフへの「パス」を構築しています...その考えに沿って、各結果をトークン化することにしました区切り文字として ">>>" を使用すると、その行にあるノードが表示されます。次に、これらのノードをループして、各ノードの属性を取得する「~」で各ノードをトークン化します。
したがって、各 ROW を処理するための for ループがあり、基本的に、処理されるノードがリーフではない場合、その ID を配列に追加して、処理される最終的なリーフに到達するためのパスを追跡することを決定します。その後、最終的に LEAF に到達したら、途中でコンパイルした PATH を使用して、ノードを挿入する関数を呼び出すことができます。
うまくいけば、すべてが理にかなっています..だから私は以下のコードを含めました..上記の2番目の結果を考えてみましょう。その結果全体を処理し、関数 insertNodeInTreeV2() を呼び出そうとすると、配列は次のようになります...
$fullTree
[1] でインデックス付けされた 1 つの要素を持つ配列です。その要素には、次の 4 つの要素を持つ配列が含まれます: ID(1)
、NAME(root)
、Description(the root node)
、CHILDREN(empty array)
$pathEntries
要素が 1 つのみ (1) の配列です。つまり、挿入される LEAF ノードへの PATH は、ルート ノードであるノード [1] によるものです。
$nodeToInsert
ID(2)
、NAME(category1)
、Description(First Category)
、 の4 つの要素を持つ配列です。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 の内容を Eclipse デバッガーの新しい Expression に貼り付けても、空の配列が表示されます。これは $fullTree[1]['CHILDREN'] にあるため、意味があります。
しかし、代わりに、ランタイムは次のエラーを教えてくれます...
troller.php 行 85 - 未定義の変数: fullTree[1]['CHILDREN']
これに関するヘルプは大歓迎です...そして、私が構築しようとしている階層配列に説明した結果セットから取得するためのより良い方法があれば、より良い方法を採用したいと思っています。
上記の関数を呼び出すコードを追加するために更新 -- for ループは、上記のようにデータベース結果の行を処理します。
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 );
}
}
}