Sankey diagramm,使用PHP

时间:2016-09-03 19:19:19

标签: javascript php mysql d3.js multidimensional-array

我想为d3.sankey创建一个多维数组。

但我不知道如何构建一个多维数组。

我需要的是:

d3.Sankey需要一个输入,如:

{
"nodes":[
{"node":0,"name":"node0"},
{"node":1,"name":"node1"},
{"node":2,"name":"node2"},
{"node":3,"name":"node3"},
{"node":4,"name":"node4"}
],
"links":[
{"source":0,"target":2,"value":2},
{"source":1,"target":2,"value":2},
{"source":1,"target":3,"value":2},
{"source":0,"target":4,"value":2},
{"source":2,"target":3,"value":2},
{"source":2,"target":4,"value":2},
{"source":3,"target":4,"value":4}
]}

实际上我用字符串构建那个东西。那听起来真的很复杂,而且确实很复杂。一个错误,它不再起作用了。

所以我的问题是如何使用数组构建该表单。

首先,我打电话给数据库,给我所有来自的输入和输入表。 看起来像:(是的,我来自德国,因此该查询中的一些单词是德语单词;))

$stmt = self::$_db->prepare("SELECT BalancesheetInput.RessourceName, "
            . "SUM(BalancesheetInput.Amount) AS Amount, "
            . "Einheiten.Einheit AS Unit "
            . "FROM BalancesheetInput "
            . "INNER JOIN Einheiten ON Unit_FK = Unit_ID "
            . "GROUP BY BalancesheetInput.RessourceName");
        $stmt->execute();

        $fetcharray = $stmt->fetchALL(PDO::FETCH_ASSOC);

那"输入"查询获取节点和链接的条目,这些条目应该引用位于sankey图中间的一个节点(为了更好地理解我添加了图片

下一步我需要输出表中的所有条目

 $stmtOutput = self::$_db->prepare("SELECT BalancesheetOutput.RessourceName, "
            ."SUM(BalancesheetOutput.Amount) AS AmountOutput, "
            ."Einheiten.Einheit AS UnitOutput "
            ."FROM BalancesheetOutput "
            ."INNER JOIN Einheiten ON Unit_FK = Unit_ID "
            ."GROUP BY BalancesheetOutput.RessourceName");
        $stmtOutput->execute();
        $fetcharrayOutput = $stmtOutput->fetchAll(PDO::FETCH_ASSOC);

所有这些条目都是从中间的节点引用它的自我(希望你理解我的意思)

我正在做什么是获取输入和输出查询并通过创建一个非常长的字符串将它们放在一起。

$counter = 0;
    $ziel = count($fetcharray);
    $array_values = count($fetcharray);

    $counterafterInput = 0;

    $jsonNodes ='{"nodes":[';
    $jsonLinkes = '],"links":[';
    foreach ($fetcharray as $getnodes){

        if (($array_values-1) == $counter) {
           // saves node to string,
            //// wenn letzer Datenbankeintrag erreicht ist addet Schöneweide als Node
            $jsonNodes .= '{"node":'. $counter. ',"name":"' . $getnodes['RessourceName'] . '","units":"'.$getnodes['Unit'].'"},';
            $jsonNodes .= '{"node":'. ($counter+1). ',"name":"Schöneweide","units":"Blackbox"},';
           // $jsonNodes .= '{"node":'. ($counter+2). ',"name":"weiter","units":"'.$getnodes['Unit'].'"},'; //irgendwann obsolete

            // saves node to string, wenn letzer Datenbankeintrag erreicht ist
            $jsonLinkes .= '{"source":'.$counter .',"target":' .$ziel .  ',"value":' . $getnodes['Amount'] . ',"units":"'.$getnodes['Unit'].'"},';
           // $jsonLinkes .= '{"source":'.($counter+1) .',"target":' .($ziel+1) .  ',"value":' . $getnodes['Amount'] . ',"units":"'.$getnodes['Unit'].'"}';

            $counter++;
            $counterafterInput = $counter;
            $counter++;

        }
        else{
        //saves nodes to string while counter != Anzahl der Datenbankeinträge
        //If else weil durch Komma getrennte Schreibeweise die nodes und Links eingetragen werden .... geht in die if ,wenn der vorletzte eintrag erreicht wird um
        //die letze Node anzuhängen. Die letzte Node ist die Blackbox Schöneweide(oder später auch ein anderes Gebiet

            $jsonNodes .= '{"node":'. $counter. ',"name":"' . $getnodes['RessourceName'] . '","units":"'.$getnodes['Unit'].'"},';
            $jsonLinkes .= '{"source":'.$counter .',"target":' .$ziel .  ',"value":' . $getnodes['Amount'] . ',"units":"'.$getnodes['Unit'].'"},';


        $counter++;
    }
    }

    $counterOutput = 0;

    $array_values_output = count($fetcharrayOutput);
    $jsnonnodesOutput = "";
    $jsonLinkesOutput = "";


    foreach ($fetcharrayOutput as $getnodesOutput)
    {
        if (($array_values_output-1) == $counterOutput){

        $jsnonnodesOutput .= '{"node":'.$counter.',"name":"'.$getnodesOutput['RessourceName'].'","units":"'.$getnodesOutput['UnitOutput'].'"}';
        $jsonLinkesOutput .= '{"source":'.$counterafterInput.',"target":'.$counter.',"value":'.$getnodesOutput['AmountOutput'].',"units":"'.$getnodesOutput['UnitOutput'].'"}]}';
        }
        else
        {
            $jsnonnodesOutput .= '{"node":'.$counter.',"name":"'.$getnodesOutput['RessourceName'].'","units":"'.$getnodesOutput['UnitOutput'].'"},';
            $jsonLinkesOutput .= '{"source":'.$counterafterInput.',"target":'.$counter.',"value":'.$getnodesOutput['AmountOutput'].',"units":"'.$getnodesOutput['UnitOutput'].'"},';
            $counterOutput++;
            $counter++;
        }


    }

    $JSONstring = $jsonNodes. $jsnonnodesOutput . $jsonLinkes .$jsonLinkesOutput;


   return $JSONstring;

让我解释一下我在做什么:

第一步我设置了一个计数器。 接下来,我计算Query中的所有条目以将节点设置在中间。 例如,我有5个条目,所以我需要将中间的节点设置为6。 Nextstep正在初始化

`$jsonNodes ='{"nodes":[';`

下一步我运行foreach循环来填充字符串中的所有条目我需要得到类似的东西

{"node":0,"name":"node0"},

我的代码就是

 $jsonNodes .= '{"node":'. $counter. ',"name":"' . $getnodes['RessourceName'] . '","units":"'.$getnodes['Unit'].'"},';

计数器计算每个entrie的ID

我也必须设置链接。所以节点引用中间的节点

 $jsonLinkes .= '{"source":'.$counter .',"target":' .$ziel .  ',"value":' . $getnodes['Amount'] . ',"units":"'.$getnodes['Unit'].'"},';

因此,source与节点中的ID相同,target是中间数量的节点,单位是自解释的。

简而言之,我做同样的事情就是得到输出只是源是中间的节点而目标是它自己的每个节点

实际上它有效,但我认为阵列有更好的解决方案。

所以现在我需要帮助来创建一个我可以保存为Javascript变量的数组。

如果有人知道它是如何工作的并告诉我。那太棒了!

1 个答案:

答案 0 :(得分:1)

使用数组的更好解决方案是使用您想要的结构构建一个数组,然后通过json_encode()运行它:

$nodes = array();
$nodes[] = array('node' => 0, 'name' => 'node0');
$nodes[] = array('node' => 1, 'name' => 'node1');
$nodes[] = array('node' => 2, 'name' => 'node2');

$links = array();
$links[] = array('source' => 0, 'target' => 2, 'value' => 2);
$links[] = array('source' => 0, 'target' => 1, 'value' => 2);

echo json_encode(array('nodes' => $nodes, 'links' => $links));
// {"nodes":[{"node":0,"name":"node0"},{"node":1,"name":"node1"},{"node":2,"name":"node2"}],"links":[{"source":0,"target":2,"value":2},{"source":0,"target":1,"value":2}]}